| |
|
|
| window.onload = function() { |
| startAnim('#animPreviewStatic'); |
| initDB().then(() => { |
| loadHome(); |
| }); |
| syncModeButtons(); |
| initLanguagesList(); |
| applyDemoLanguage('fa'); |
| |
| const timeline = document.getElementById('timelineScroll'); |
| timeline.addEventListener('touchstart', () => { v.pause(); togglePlayIcon(false); }, {passive: true}); |
| timeline.addEventListener('mousedown', () => { v.pause(); togglePlayIcon(false); }); |
|
|
| |
| v.addEventListener('play', () => { |
| const vBars = tEl.querySelectorAll('.v-bar'); |
| vBars.forEach(b => b.style.animationPlayState = 'running'); |
| }); |
| v.addEventListener('pause', () => { |
| const vBars = tEl.querySelectorAll('.v-bar'); |
| vBars.forEach(b => b.style.animationPlayState = 'paused'); |
| }); |
| }; |
|
|
| window.onresize = fit; |
|
|
| |
| function runFastSync() { |
| |
| if (!v.paused || manualOverride) { |
| const cur = v.currentTime; |
| |
| const timeDisplay = document.getElementById('globalTimeDisplay'); |
| if (timeDisplay) { |
| timeDisplay.innerText = `${formatTimeSimple(cur)} / ${formatTimeSimple(v.duration || 0)}`; |
| } |
| |
| if (!v.paused) manualOverride = false; |
|
|
| let foundWord = false; |
| |
| for (let s = 0; s < state.segs.length; s++) { |
| const seg = state.segs[s]; |
| if (cur >= seg.start && cur < (seg.end + 0.1)) { |
| if (seg.words) { |
| for (let w = 0; w < seg.words.length; w++) { |
| const word = seg.words[w]; |
| |
| if (cur >= (word.start - 0.02) && cur < (word.end + 0.05)) { |
| const uid = `${s}-${w}`; |
| if (activeWordId !== uid) { |
| activeWordId = uid; |
| document.querySelectorAll('.word-chip').forEach(c => c.classList.remove('active')); |
| const el = document.getElementById(`w-${uid}`); |
| if(el) { |
| el.classList.add('active'); |
| if(!manualOverride) el.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); |
| } |
| updateSplitButton(); |
| } |
| foundWord = true; |
| break; |
| } |
| } |
| } |
| } |
| if (foundWord) break; |
| } |
|
|
| if (!foundWord && !manualOverride) { |
| document.querySelectorAll('.word-chip').forEach(c => c.classList.remove('active')); |
| activeWordId = null; |
| const toolbar = document.getElementById('toolbar'); |
| if (toolbar) toolbar.classList.remove('show'); |
| } |
| |
| updateOverlayContent(cur); |
| } |
| |
| requestAnimationFrame(runFastSync); |
| } |
|
|
| |
| requestAnimationFrame(runFastSync); |
|
|
| |
|
|
| |
| const touchAreaStyle = document.createElement('style'); |
| touchAreaStyle.innerHTML = ` |
| /* ایجاد یک حاشیه نامرئی ۱۰۰ پیکسلی دور متن تا کاربر راحتتر آن را بگیرد */ |
| #activeText::before { |
| content: ''; |
| position: absolute; |
| top: -100px; bottom: -100px; left: -100px; right: -100px; |
| z-index: 999; |
| } |
| /* مستطیل سفید که هنگام جابجایی ظاهر میشود */ |
| #activeText.is-dragging { |
| outline: 2px solid #ffffff; |
| outline-offset: 20px; |
| border-radius: 8px; |
| transition: outline 0.1s; |
| } |
| `; |
| document.head.appendChild(touchAreaStyle); |
|
|
| |
| tEl.style.touchAction = 'none'; |
|
|
| tEl.addEventListener('touchstart', (e) => { |
| |
| if (v && !v.paused) { |
| v.pause(); |
| if (typeof togglePlayIcon === 'function') togglePlayIcon(false); |
| } |
|
|
| |
| e.preventDefault(); |
| e.stopPropagation(); |
|
|
| if(e.touches.length === 1) { |
| touchMode = 'drag'; |
| initialY = e.touches[0].clientY; |
| initialX = e.touches[0].clientX; |
| initialBottom = state.st.y; |
| initialXState = state.st.x || 0; |
| |
| tEl.classList.add('is-dragging'); |
|
|
| } else if (e.touches.length === 2) { |
| touchMode = 'pinch'; |
| initialDist = Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY); |
| initialFontSize = state.st.fz; |
| tEl.classList.add('is-dragging'); |
| } |
| }, {passive: false}); |
|
|
| tEl.addEventListener('touchmove', (e) => { |
| if (!touchMode) return; |
| e.preventDefault(); |
| e.stopPropagation(); |
| |
| |
| if (e.touches.length === 2) { |
| if (touchMode !== 'pinch') { |
| touchMode = 'pinch'; |
| initialDist = Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY); |
| initialFontSize = state.st.fz; |
| } |
| |
| let dist = Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY); |
| if (initialDist > 0) { |
| let newSize = initialFontSize * (dist / initialDist); |
| state.st.fz = Math.round(Math.max(10, Math.min(150, newSize))); |
| tEl.style.fontSize = state.st.fz + 'px'; |
| syncUIWithState(); |
| } |
| |
| } else if (touchMode === 'drag' && e.touches.length === 1) { |
| let diffY = (initialY - e.touches[0].clientY) * 1.8; |
| let newBottom = initialBottom + diffY; |
| state.st.y = Math.round(newBottom); |
|
|
| let diffX = (e.touches[0].clientX - initialX) * 1.5; |
| let newX = initialXState + diffX; |
| state.st.x = Math.round(newX); |
|
|
| |
| tEl.style.bottom = state.st.y + 'px'; |
| tEl.style.transform = `translateX(calc(-50% + ${state.st.x || 0}px))`; |
| syncUIWithState(); |
| } |
| }, {passive: false}); |
|
|
| tEl.addEventListener('touchend', () => { |
| touchMode = null; |
| |
| tEl.classList.remove('is-dragging'); |
| |
| upd(); |
| }); |