Spaces:
Paused
Paused
File size: 7,636 Bytes
8e64a96 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | // راهاندازی اولیه و هندلرهای رویداد اصلی
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;
// --- موتور زمانسنج هوشمند (High-Precision Sync) جایگزین v.ontimeupdate ---
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;
// اضافه کردن 0.1 ثانیه تلورانس برای دیده شدن کلمات آخر جمله
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();
}); |