document.addEventListener('DOMContentLoaded', () => { const dial = document.getElementById('dial'); const fingerStop = document.getElementById('finger-stop'); const display = document.getElementById('dialed-numbers'); const callButton = document.getElementById('call-button'); const clearButton = document.getElementById('clear-button'); const dialReturnSound = document.getElementById('dial-return-sound'); const dialClickSound = document.getElementById('dial-click-sound'); if (!dialClickSound) console.error("Audio element #dial-click-sound not found!"); if (!dialReturnSound) console.warn("Audio element #dial-return-sound not found (optional)."); const numbers = ['0', '9', '8', '7', '6', '5', '4', '3', '2', '1']; const numHoles = 10; // --- Config --- const holeAngleOffset = -55; const holeAngleSeparation = 30; const fingerStopTargetAngle = holeAngleOffset + (numHoles * holeAngleSeparation) + 1; const dialPlateRadius = dial.offsetWidth / 2; const holeRadius = dialPlateRadius * 0.72; const numberPlacementRadius = holeRadius * 0.65; // Inner radius const DIAL_RETURN_DURATION_MS = 550; const CLICK_START_DELAY_MS = 50; // --- State --- let isDragging = false; let startAngle = 0; let currentRotation = 0; let activeHole = null; let maxRotationAngle = 0; let dialedDigit = null; let holeData = {}; let clickTimer = null; // --- Generate Holes and Numbers on Dial Plate --- numbers.forEach((num, index) => { const angle = holeAngleOffset + index * holeAngleSeparation; const rad = angle * (Math.PI / 180); // --- Create Hole --- const holeX = holeRadius * Math.cos(rad); const holeY = holeRadius * Math.sin(rad); const hole = document.createElement('div'); hole.classList.add('hole'); hole.dataset.number = num; hole.style.transform = `translate(${holeX}px, ${holeY}px)`; dial.appendChild(hole); // --- Create Number --- const numRad = angle * (Math.PI / 180); const numX = numberPlacementRadius * Math.cos(numRad); // Use inner radius const numY = numberPlacementRadius * Math.sin(numRad); // Use inner radius const numElement = document.createElement('div'); numElement.classList.add('dial-plate-number'); numElement.textContent = num; // 1. Position using left/top relative to dial center numElement.style.left = `calc(50% + ${numX}px)`; numElement.style.top = `calc(50% + ${numY}px)`; // 2. Apply ONLY the centering translation. NO ROTATION. numElement.style.transform = `translate(-50%, -50%)`; // REMOVED rotate() part // The numbers will now inherit the rotation of the parent #dial div. dial.appendChild(numElement); // Store info holeData[index] = { element: hole, number: num, startAngle: angle }; // Attach Event Listeners hole.addEventListener('mousedown', startDrag); hole.addEventListener('touchstart', startDrag, { passive: false }); }); // --- Position Finger Stop (Same as before) --- const stopRad = fingerStopTargetAngle * (Math.PI / 180); const stopRadius = dialPlateRadius * 0.95; const stopX = stopRadius * Math.cos(stopRad); const stopY = stopRadius * Math.sin(stopRad); fingerStop.style.left = `calc(50% + ${stopX}px - 9px)`; fingerStop.style.top = `calc(50% + ${stopY}px - 22.5px)`; fingerStop.style.transform = `rotate(${fingerStopTargetAngle + 90}deg)`; // --- Drag Logic (Remains the same) --- function startDrag(e) { if (isDragging) return; if (clickTimer) clearInterval(clickTimer); const evt = e.touches ? e.touches[0] : e; activeHole = evt.target.closest('.hole'); if (!activeHole) return; const holeInfo = Object.values(holeData).find(data => data.element === activeHole); if (!holeInfo) return; isDragging = true; dialedDigit = holeInfo.number; activeHole.classList.add('dragging'); dial.style.transition = 'none'; const rect = dial.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; startAngle = getAngle(evt.clientX, evt.clientY, centerX, centerY) - currentRotation; maxRotationAngle = 0; document.addEventListener('mousemove', drag); document.addEventListener('mouseup', endDrag); document.addEventListener('touchmove', drag, { passive: false }); document.addEventListener('touchend', endDrag); if (e.touches) e.preventDefault(); } function drag(e) { if (!isDragging || !activeHole) return; const evt = e.touches ? e.touches[0] : e; const rect = dial.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; let currentMouseAngle = getAngle(evt.clientX, evt.clientY, centerX, centerY); let potentialRotation = currentMouseAngle - startAngle; let delta = potentialRotation - currentRotation; if (delta > 180) delta -= 360; if (delta < -180) delta += 360; potentialRotation = currentRotation + delta; potentialRotation = Math.max(0, potentialRotation); const holeInfo = Object.values(holeData).find(data => data.element === activeHole); let holeStartAngle = holeInfo.startAngle; let maxAllowedRotation = fingerStopTargetAngle - holeStartAngle; if (maxAllowedRotation < 0) maxAllowedRotation += 360; potentialRotation = Math.min(potentialRotation, maxAllowedRotation); currentRotation = potentialRotation; maxRotationAngle = Math.max(maxRotationAngle, currentRotation); dial.style.transform = `rotate(${currentRotation}deg)`; if (e.touches) e.preventDefault(); } function endDrag() { if (!isDragging) return; document.removeEventListener('mousemove', drag); document.removeEventListener('mouseup', endDrag); document.removeEventListener('touchmove', drag); document.removeEventListener('touchend', endDrag); let numberSuccessfullyDialed = false; let digitToPlaySoundFor = null; if (activeHole) { activeHole.classList.remove('dragging'); const holeInfo = Object.values(holeData).find(data => data.element === activeHole); const rotationThreshold = 10; let holeStartAngle = holeInfo.startAngle; let expectedStopRotation = fingerStopTargetAngle - holeStartAngle; if (expectedStopRotation < 0) expectedStopRotation += 360; const tolerance = 2; if (maxRotationAngle > rotationThreshold && maxRotationAngle >= expectedStopRotation - tolerance) { appendNumber(dialedDigit); numberSuccessfullyDialed = true; digitToPlaySoundFor = dialedDigit; } } dial.style.transition = `transform ${DIAL_RETURN_DURATION_MS / 1000}s cubic-bezier(0.15, 0.85, 0.25, 1)`; dial.style.transform = 'rotate(0deg)'; if (numberSuccessfullyDialed) { playDialClickSounds(digitToPlaySoundFor); } isDragging = false; startAngle = 0; currentRotation = 0; activeHole = null; dialedDigit = null; } // --- Helper Functions (Remain the same) --- function getAngle(x, y, centerX, centerY) { const deltaX = x - centerX; const deltaY = y - centerY; let angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI); return angle; } function appendNumber(num) { if (display.textContent.length < 10) { display.textContent += num; } } function clearDisplay() { display.textContent = ''; if (clickTimer) clearInterval(clickTimer); } // --- Sound Playback Logic using