Проблема на iPhone:
- Первый видеокадр появляется случайно, не синхронизируется с прокруткой.
- Прокрутка происходит с задержкой или заикается, а видео зависает. кажется
неотзывчивым. - Иногда видео вообще не загружается должным образом, и для его появления требуется ручное
подталкивание прокрутки.
- Я использую элемент и вручную обновляю его currentTime
на основе прогресса прокрутки. - После определенного порога прокрутки видео воспроизводится автоматически в
цикле. - Я предварительно загружаю видео, отключаю его и проверяю, что оно использует playInline для совместимости с iOS.
- На iOS я «запускаю» видео с тихим воспроизведением/паузой при сенсорном запуске, чтобы
соответствовать автозапуску политики.
Код: Выделить всё
class ScrollVideoController {
constructor() {
this.video = document.querySelector('.animate-on-scroll');
this.sticky = document.querySelector('.scroll-sticky');
this.container = document.querySelector('.scroll-video-animation');
this.progressBar = document.querySelector('.progress-bar');
this.content = document.querySelector('.scroll-video-animation .content');
this.contentHalfHalf = document.querySelector('.scroll-video-animation .content-half-half');
this.header = document.querySelector("#new-fixed-header-styling");
if (!this.video || !this.sticky || !this.container) return;
this.isIOS = /iPhone|iPad|iPod/.test(navigator.userAgent);
this.isMobile = window.innerWidth {
this.isReady = true;
this.video.classList.add('ready');
this.loadingOverlay.classList.add('hidden');
});
this.video.addEventListener('canplay', () => {
this.loadingOverlay.classList.add('hidden');
});
this.video.addEventListener('error', () => {
this.loadingOverlay.classList.add('hidden');
this.errorOverlay.classList.remove('hidden');
});
this.video.addEventListener('ended', () => {
const frameTime = this.loopStartFrame / this.frameRate;
this.video.currentTime = frameTime;
if (this.isAutoplaying) {
this.video.play().catch(() => {});
}
});
if (this.isIOS) {
const primeVideo = async () => {
try {
await this.video.play();
this.video.pause();
this.video.currentTime = 0;
} catch (error) {
console.warn('Video priming failed:', error);
}
window.removeEventListener('touchstart', primeVideo);
};
window.addEventListener('touchstart', primeVideo, {
once: true
});
}
window.addEventListener('resize', () => {
this.isMobile = window.innerWidth = 0.9) {
this.header.style.opacity = "0";
this.header.style.pointerEvents = "none";
} else {
this.header.style.opacity = "1";
this.header.style.pointerEvents = "auto";
}
}
// Content opacity
if (this.content) {
const contentOpacity = Math.max(0, 1 - (scrollData.progress * (1 / 0.45)));
this.content.style.opacity = contentOpacity.toString();
}
// Content-half-half fade in
if (this.contentHalfHalf) {
const halfHalfOpacity = scrollData.progress >= 0.6 ? Math.min(1, (scrollData.progress - 0.6) * (1 / 0.2)) : 0;
this.contentHalfHalf.style.opacity = halfHalfOpacity.toString();
}
if (scrollData.stickyTop > 0) {
this.isAutoplaying = false;
this.video.pause();
this.video.currentTime = 0;
return;
}
if (scrollData.progress < 0.55) {
const frameNumber = Math.floor(scrollData.progress * (this.scrollThreshold / 0.55));
const frameTime = frameNumber / this.frameRate;
if (this.isAutoplaying) {
this.isAutoplaying = false;
this.video.pause();
}
const timeDiff = Math.abs(this.video.currentTime - frameTime);
if (timeDiff > (this.isMobile ? 0.5 : 0.1)) {
this.video.currentTime = frameTime;
}
} else if (!this.isAutoplaying) {
this.isAutoplaying = true;
const startFrame = this.scrollThreshold / this.frameRate;
this.video.currentTime = startFrame;
this.video.play().catch(() => {});
}
if (this.progressBar) {
this.progressBar.style.width = `${scrollData.progress * 100}%`;
const progressBarContainer = this.progressBar.parentElement;
if (progressBarContainer) {
if (scrollData.progress >= 0.98) {
progressBarContainer.style.opacity = '0';
progressBarContainer.style.transition = 'opacity 0.5s ease-out';
} else if (scrollData.progress < 0.95) {
progressBarContainer.style.opacity = '1';
progressBarContainer.style.transition = 'opacity 0.3s ease-in';
}
}
}
}
animate() {
const scrollData = this.getScrollProgress();
this.updateVideo(scrollData);
this.rafId = requestAnimationFrame(() => this.animate());
}
}Код: Выделить всё
//ONLY TEXT CONTENT HERE
//ONLY TEXT CONTENT HERE
//ONLY TEXT CONTENT HERE
Подробнее здесь: https://stackoverflow.com/questions/795 ... amically-w