JIGOKU YŌDEN
CALENDARIO
地獄妖殿
00
MES
0000
00
DÍA
ANIMAL
const jyCalendarBaseWidth = 1200; const jyCalendarBaseHeight = 480; function jyCalendarScale() { const wrap = document.querySelector(".jy-scale-wrap"); const inner = document.querySelector(".jy-scale-inner"); const cal = document.querySelector(".jy-cal"); if (!wrap || !inner || !cal) return; const wrapStyles = window.getComputedStyle(wrap); const paddingLeft = parseFloat(wrapStyles.paddingLeft); const paddingRight = parseFloat(wrapStyles.paddingRight); const availableWidth = wrap.clientWidth - paddingLeft - paddingRight; const scale = availableWidth / jyCalendarBaseWidth; cal.style.transform = "scale(" + scale + ")"; inner.style.height = jyCalendarBaseHeight * scale + "px"; } window.addEventListener("load", jyCalendarScale); window.addEventListener("resize", jyCalendarScale); document.addEventListener("DOMContentLoaded", jyCalendarScale); const jyCalendarMonths = [ "ENERO", "FEBRERO", "MARZO", "ABRIL", "MAYO", "JUNIO", "JULIO", "AGOSTO", "SEPTIEMBRE", "OCTUBRE", "NOVIEMBRE", "DICIEMBRE" ]; const jyCalendarWeekdays = [ "DOMINGO", "LUNES", "MARTES", "MIÉRCOLES", "JUEVES", "VIERNES", "SÁBADO" ]; const jyCalendarAnimals = { 1: { name: "PANTERA", icon: "https://jigokuyoden.com/assets/images/image35.png?v=dc217124" }, 2: { name: "SERPIENTE", icon: "https://jigokuyoden.com/assets/images/image42.png?v=dc217124" }, 3: { name: "BUEY", icon: "https://jigokuyoden.com/assets/images/image40.png?v=dc217124" }, 4: { name: "LOBO", icon: "https://jigokuyoden.com/assets/images/image41.png?v=dc217124" }, 5: { name: "CONEJO", icon: "https://jigokuyoden.com/assets/images/image36.png?v=dc217124" }, 6: { name: "CARNERO", icon: "https://jigokuyoden.com/assets/images/image38.png?v=dc217124" }, 7: { name: "RATA", icon: "https://jigokuyoden.com/assets/images/image37.png?v=dc217124" }, 8: { name: "DRAGÓN", icon: "https://jigokuyoden.com/assets/images/image43.png?v=dc217124" }, 9: { name: "CABALLO", icon: "https://jigokuyoden.com/assets/images/image39.png?v=dc217124" } }; function jyCalendarReduceToNine(num) { while (num > 9) { num = num .toString() .split("") .reduce((sum, digit) => sum + Number(digit), 0); } return num; } function jyCalendarGetDateParts() { const now = new Date(); const day = now.getDate(); const month = now.getMonth() + 1; const year = now.getFullYear(); const weekday = now.getDay(); return { day: day, dayPadded: String(day).padStart(2, "0"), month: month, monthPadded: String(month).padStart(2, "0"), monthName: jyCalendarMonths[month - 1], year: year, weekdayName: jyCalendarWeekdays[weekday] }; } function jyCalendarGetAnimalNumber(parts) { const fullDate = parts.dayPadded + parts.monthPadded + String(parts.year); const sum = fullDate .split("") .reduce((total, digit) => total + Number(digit), 0); return jyCalendarReduceToNine(sum); } function jyCalendarUpdate() { const parts = jyCalendarGetDateParts(); const animalNumber = jyCalendarGetAnimalNumber(parts); const animal = jyCalendarAnimals[animalNumber]; document.getElementById("jyCalMonthNum").textContent = parts.dayPadded; document.getElementById("jyCalMonthName").textContent = parts.monthName; document.getElementById("jyCalYear").textContent = parts.year; document.getElementById("jyCalAnimalNum").textContent = String(animalNumber).padStart(2, "0"); document.getElementById("jyCalWeekday").textContent = parts.weekdayName; document.getElementById("jyCalAnimal").textContent = animal.name; const icon = document.getElementById("jyCalAnimalIcon"); if (animal.icon) { icon.src = animal.icon; icon.alt = animal.name; icon.style.visibility = "visible"; } else { icon.removeAttribute("src"); icon.alt = ""; icon.style.visibility = "hidden"; } jyCalendarScale(); } document.addEventListener("DOMContentLoaded", jyCalendarUpdate); window.addEventListener("load", jyCalendarUpdate);
¿CUÁL ES TU ANIMAL DE NACIMIENTO?
INSERTA TU FECHA DE NACIMIENTO
DÍA
MES
AÑO
CALCULAR
const jyBirthBaseWidth = 1200; const jyBirthBaseHeight = 390; const jyBirthErrorIcon = "https://jigokuyoden.com/assets/images/image44.png?v=dc217124"; function jyScaleBirthCalculator() { const wrap = document.querySelector(".jy-birth-wrap"); const inner = document.querySelector(".jy-birth-inner"); const calc = document.querySelector(".jy-birth-calc"); if (!wrap || !inner || !calc) return; const wrapStyles = window.getComputedStyle(wrap); const paddingLeft = parseFloat(wrapStyles.paddingLeft); const paddingRight = parseFloat(wrapStyles.paddingRight); const availableWidth = wrap.clientWidth - paddingLeft - paddingRight; const scale = availableWidth / jyBirthBaseWidth; calc.style.transform = "scale(" + scale + ")"; inner.style.height = jyBirthBaseHeight * scale + "px"; } window.addEventListener("load", jyScaleBirthCalculator); window.addEventListener("resize", jyScaleBirthCalculator); document.addEventListener("DOMContentLoaded", jyScaleBirthCalculator); const jyBirthAnimals = { 1: { animal: "PANTERA", title: "LA SOMBRA", traits: "SIGILO, SOLEDAD", icon: "https://jigokuyoden.com/assets/images/image35.png?v=dc217124" }, 2: { animal: "SERPIENTE", title: "EL CONOCIMIENTO", traits: "ASTUCIA, MANIPULACIÓN", icon: "https://jigokuyoden.com/assets/images/image42.png?v=dc217124" }, 3: { animal: "BUEY", title: "LA FUERZA", traits: "RESISTENCIA, OBSTINACIÓN", icon: "https://jigokuyoden.com/assets/images/image40.png?v=dc217124" }, 4: { animal: "LOBO", title: "EL LÍDER", traits: "PROTECCIÓN, VENGANZA", icon: "https://jigokuyoden.com/assets/images/image41.png?v=dc217124" }, 5: { animal: "CONEJO", title: "EL ESPÍRITU", traits: "RAPIDEZ, EVASIÓN", icon: "https://jigokuyoden.com/assets/images/image36.png?v=dc217124" }, 6: { animal: "CARNERO", title: "EL IMPULSO", traits: "DECISIÓN, TEMERIDAD", icon: "https://jigokuyoden.com/assets/images/image38.png?v=dc217124" }, 7: { animal: "RATA", title: "LA MENTE", traits: "INGENIO, TRAICIÓN", icon: "https://jigokuyoden.com/assets/images/image37.png?v=dc217124" }, 8: { animal: "DRAGÓN", title: "EL PODER", traits: "DOMINIO, ARROGANCIA", icon: "https://jigokuyoden.com/assets/images/image43.png?v=dc217124" }, 9: { animal: "CABALLO", title: "LA LIBERTAD", traits: "INDEPENDENCIA, INCONSTANCIA", icon: "https://jigokuyoden.com/assets/images/image39.png?v=dc217124" } }; function jyBirthReduceToNine(num) { while (num > 9) { num = num .toString() .split("") .reduce((sum, digit) => sum + Number(digit), 0); } return num; } function jyBirthOnlyNumbers(value) { return value.replace(/\D/g, ""); } function jyBirthFormatInputs() { const dayInput = document.getElementById("jyDayInput"); const monthInput = document.getElementById("jyMonthInput"); const yearInput = document.getElementById("jyYearInput"); dayInput.value = jyBirthOnlyNumbers(dayInput.value).slice(0, 2); monthInput.value = jyBirthOnlyNumbers(monthInput.value).slice(0, 2); yearInput.value = jyBirthOnlyNumbers(yearInput.value).slice(0, 4); } function jyBirthPadDayMonth() { const dayInput = document.getElementById("jyDayInput"); const monthInput = document.getElementById("jyMonthInput"); if (dayInput.value.length === 1) { dayInput.value = dayInput.value.padStart(2, "0"); } if (monthInput.value.length === 1) { monthInput.value = monthInput.value.padStart(2, "0"); } } function jyBirthIsValidDate(day, month, year) { if (!day || !month || !year) return false; if (year.length !== 4) return false; const d = Number(day); const m = Number(month); const y = Number(year); if (d < 1 || d > 31) return false; if (m < 1 || m > 12) return false; if (y < 1) return false; const testDate = new Date(y, m - 1, d); return ( testDate.getFullYear() === y && testDate.getMonth() === m - 1 && testDate.getDate() === d ); } function jyBirthGetAnimalNumber(day, month, year) { const fullDate = String(day).padStart(2, "0") + String(month).padStart(2, "0") + String(year).padStart(4, "0"); const sum = fullDate .split("") .reduce((total, digit) => total + Number(digit), 0); return jyBirthReduceToNine(sum); } function jyBirthShowResult(number) { const data = jyBirthAnimals[number]; const result = document.getElementById("jyResult"); const iconWrap = document.getElementById("jyResultIconWrap"); document.getElementById("jyResultNumber").textContent = String(number).padStart(2, "0"); document.getElementById("jyResultAnimal").textContent = data.animal; document.getElementById("jyResultTitle").textContent = data.title; document.getElementById("jyResultTraits").textContent = data.traits; const icon = document.getElementById("jyResultIcon"); icon.src = data.icon; icon.alt = data.animal; result.classList.remove("jy-result-hidden"); iconWrap.classList.remove("jy-result-hidden"); result.classList.remove("jy-error"); } function jyBirthShowError() { const result = document.getElementById("jyResult"); const iconWrap = document.getElementById("jyResultIconWrap"); document.getElementById("jyResultNumber").textContent = "--"; document.getElementById("jyResultAnimal").textContent = "ERROR"; document.getElementById("jyResultTitle").textContent = "FECHA INVÁLIDA"; document.getElementById("jyResultTraits").textContent = "REVISA DÍA, MES Y AÑO"; const icon = document.getElementById("jyResultIcon"); icon.src = jyBirthErrorIcon; icon.alt = "ERROR"; result.classList.remove("jy-result-hidden"); iconWrap.classList.remove("jy-result-hidden"); result.classList.add("jy-error"); } function jyBirthCalculate() { jyBirthFormatInputs(); jyBirthPadDayMonth(); const day = document.getElementById("jyDayInput").value; const month = document.getElementById("jyMonthInput").value; const year = document.getElementById("jyYearInput").value; if (!jyBirthIsValidDate(day, month, year)) { jyBirthShowError(); return; } const animalNumber = jyBirthGetAnimalNumber(day, month, year); jyBirthShowResult(animalNumber); } document.getElementById("jyDayInput").addEventListener("input", jyBirthFormatInputs); document.getElementById("jyMonthInput").addEventListener("input", jyBirthFormatInputs); document.getElementById("jyYearInput").addEventListener("input", jyBirthFormatInputs); document.getElementById("jyDayInput").addEventListener("blur", function() { jyBirthFormatInputs(); jyBirthPadDayMonth(); }); document.getElementById("jyMonthInput").addEventListener("blur", function() { jyBirthFormatInputs(); jyBirthPadDayMonth(); }); document.getElementById("jyCalculateBtn").addEventListener("click", jyBirthCalculate); document.querySelectorAll(".jy-date-input").forEach(function(input) { input.addEventListener("keydown", function(event) { if (event.key === "Enter") { jyBirthCalculate(); } }); }); jyScaleBirthCalculator();
const img = document.getElementById("rotar-img"); let rotation = 0; let isDragging = false; let lastX = 0; let velocity = 0; let autoSpeed = 0.08; let friction = 0.95; function animate() { if (!isDragging) { rotation += velocity || autoSpeed; velocity *= friction; if (Math.abs(velocity) < 0.01) velocity = 0; img.style.transform = `rotate(${rotation}deg)`; } requestAnimationFrame(animate); } animate(); img.addEventListener("pointerdown", (e) => { isDragging = true; lastX = e.clientX; velocity = 0; }); window.addEventListener("pointermove", (e) => { if (!isDragging) return; const delta = e.clientX - lastX; rotation += delta * 0.6; velocity = delta * 0.12; img.style.transform = `rotate(${rotation}deg)`; lastX = e.clientX; }); window.addEventListener("pointerup", () => { isDragging = false; }); window.addEventListener("pointercancel", () => { isDragging = false; });
Button
(function () { const wrap = document.getElementById("ritualGateWrap"); const svg = document.getElementById("ritualSVG"); const ringBase = document.getElementById("ringBase"); const ringProgress = document.getElementById("ringProgress"); const handleOuter = document.getElementById("handleOuter"); const handleInner = document.getElementById("handleInner"); const cx = 200; const cy = 200; const radius = 135; const gapDeg = 42; const arcDeg = 360 - gapDeg; const startAngle = -90 + gapDeg / 2; const endAngle = startAngle + arcDeg; const circumference = 2 * Math.PI * radius; const visibleArc = circumference * (arcDeg / 360); const gapArc = circumference - visibleArc; const baseDash = `${visibleArc} ${gapArc}`; const baseOffset = -gapArc / 2; ringBase.setAttribute("stroke-dasharray", baseDash); ringBase.setAttribute("stroke-dashoffset", baseOffset); ringProgress.setAttribute("stroke-dasharray", `0 ${circumference}`); ringProgress.setAttribute("stroke-dashoffset", baseOffset); let dragging = false; let unlocked = false; let currentProgress = 0; let audioCtx = null; let audioPrimed = false; let audioReadyPromise = null; function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } function angleToXY(angleDeg) { const rad = angleDeg * Math.PI / 180; return { x: cx + radius * Math.cos(rad), y: cy + radius * Math.sin(rad) }; } function progressToAngle(progress) { return startAngle + arcDeg * progress; } function setHandleByProgress(progress) { currentProgress = clamp(progress, 0, 1); const angle = progressToAngle(currentProgress); const p = angleToXY(angle); handleOuter.setAttribute("cx", p.x); handleOuter.setAttribute("cy", p.y); handleInner.setAttribute("cx", p.x); handleInner.setAttribute("cy", p.y); const redLength = visibleArc * currentProgress; ringProgress.setAttribute( "stroke-dasharray", `${redLength} ${circumference}` ); } function getSVGPoint(e) { const pt = svg.createSVGPoint(); pt.x = e.clientX; pt.y = e.clientY; return pt.matrixTransform(svg.getScreenCTM().inverse()); } function normalize360(angle) { return (angle + 360) % 360; } function angleToProgress(angle) { const startNorm = normalize360(startAngle); const angleNorm = normalize360(angle); let diff = angleNorm - startNorm; if (diff < 0) { diff += 360; } return clamp(diff / arcDeg, 0, 1); } function getAudioContext() { const AudioContextClass = window.AudioContext || window.webkitAudioContext; if (!AudioContextClass) { console.warn("AudioContext no está disponible en este navegador."); return null; } if (!audioCtx) { audioCtx = new AudioContextClass(); } return audioCtx; } function prepareAudio() { const ctx = getAudioContext(); if (!ctx) return Promise.resolve(false); if (audioReadyPromise) { return audioReadyPromise; } audioReadyPromise = new Promise(resolve => { const resumePromise = ctx.state === "suspended" ? ctx.resume() : Promise.resolve(); resumePromise .then(() => { if (!audioPrimed) { audioPrimed = true; const now = ctx.currentTime; const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.type = "sine"; osc.frequency.setValueAtTime(440, now); gain.gain.setValueAtTime(0.001, now); gain.gain.exponentialRampToValueAtTime(0.00001, now + 0.06); osc.connect(gain); gain.connect(ctx.destination); osc.start(now); osc.stop(now + 0.07); } resolve(true); }) .catch(error => { console.warn("No se pudo activar el audio:", error); resolve(false); }); }); return audioReadyPromise; } function playTempleBell() { prepareAudio().then(isReady => { if (!isReady || !audioCtx) { console.warn("El audio no está listo."); return; } const ctx = audioCtx; const now = ctx.currentTime + 0.02; const master = ctx.createGain(); master.gain.setValueAtTime(1.0, now); master.gain.exponentialRampToValueAtTime(0.0001, now + 2.8); master.connect(ctx.destination); function tone(freq, delay, dur, vol) { const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.type = "sine"; osc.frequency.setValueAtTime(freq, now + delay); osc.frequency.exponentialRampToValueAtTime( freq * 0.982, now + delay + dur ); gain.gain.setValueAtTime(0.0001, now + delay); gain.gain.exponentialRampToValueAtTime(vol, now + delay + 0.015); gain.gain.exponentialRampToValueAtTime(0.0001, now + delay + dur); osc.connect(gain); gain.connect(master); osc.start(now + delay); osc.stop(now + delay + dur + 0.08); } tone(196, 0.00, 1.9, 0.38); tone(392, 0.01, 1.5, 0.18); tone(588, 0.02, 1.15, 0.08); tone(784, 0.025, 0.8, 0.035); tone(196, 0.30, 1.35, 0.14); tone(392, 0.34, 1.0, 0.065); }); } function unlockGate() { if (unlocked) return; unlocked = true; dragging = false; setHandleByProgress(1); wrap.classList.add("unlocked"); playTempleBell(); setTimeout(function () { wrap.classList.add("hidden"); }, 1700); } handleOuter.addEventListener("pointerdown", e => { if (unlocked) return; dragging = true; handleOuter.setPointerCapture(e.pointerId); prepareAudio(); }); svg.addEventListener("pointermove", e => { if (!dragging || unlocked) return; e.preventDefault(); const p = getSVGPoint(e); const dx = p.x - cx; const dy = p.y - cy; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < radius - 55 || distance > radius + 55) { return; } const rawAngle = Math.atan2(dy, dx) * 180 / Math.PI; const candidateProgress = angleToProgress(rawAngle); const maxJump = 0.13; if (candidateProgress > currentProgress + maxJump) { return; } if (candidateProgress < currentProgress - 0.25) { return; } setHandleByProgress(candidateProgress); if (currentProgress >= 0.985) { unlockGate(); } }); window.addEventListener("pointerup", () => { dragging = false; }); window.addEventListener("pointercancel", () => { dragging = false; }); setHandleByProgress(0); })();