Zirnavis / static /js /main.js
Transfer Bot
Moved to Hugging Face automatically
34d3ca9
Raw
History Blame Contribute Delete
7.64 kB
// راه‌اندازی اولیه و هندلرهای رویداد اصلی
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();
});