//** Start immersive-scroll JS **/ /* The encoding is super important here to enable frame-by-frame scrubbing. */ let immersiveScrollTriggers = []; function immersiveVideoOnScroll(imsVideo, video, isImmersiveAnimate) { let videoContainer = imsVideo.querySelector(".video-container"), rightContainer = imsVideo.querySelector(".right-container"), videoText = imsVideo.querySelector(".video-text-container"), reducedMotionImage = imsVideo.querySelector(".reducedmotion-image"), imsPin = imsVideo.querySelector(".immersive-pin"), src = video?.currentSrc || video?.src, scrollSpeed= video?.getAttribute("scroll-speed"); /* Scroll Control! on different viewports and rediced animation */ let animationCheckpoint = gsap.matchMedia(), breakPoint = 1084; animationCheckpoint.add({ isDesktop: `(min-width: ${breakPoint}px)`, isMobile: `(max-width: ${breakPoint - 1}px)`, reduceMotion: "(prefers-reduced-motion: reduce)", }, (context) => { let { isDesktop, isMobile, reduceMotion } = context.conditions; //Condition is to verify the desktop viewport if (isDesktop && !imsVideo.classList.contains("no-video")) { //if its true, this condition is to verify reduced animation if (isImmersiveAnimate) { rightContainer.classList.add("immersive-text-hide"); videoText.classList.remove("immersive-hide"); reducedMotionImage.classList.add("immersive-hide"); videoContainer.classList.remove("immersive-hide"); /* Make sure the video is 'activated' on devices/ios */ function activate(el, event, fn, opts) { var activateFn = function (e) { el.removeEventListener(event, activateFn); fn.apply(this, arguments); }; el.addEventListener(event, activateFn, opts); return activateFn; } //Play video on scroll through for touch devices activate(document.documentElement, "touchstart", function (e) { video.play(); video.pause(); }); //Register ScrollTrigger to initiate the on scroll functionlity for immersive scroll gsap.registerPlugin(ScrollTrigger); let imsvideo = gsap.timeline({ // currentTime: 20, defaults: { duration: 24, ease: "none" }, scrollTrigger: { trigger: videoContainer, start: "top top", end: "+="+(scrollSpeed)+" bottom", pin: isDesktop ? imsPin : reduceMotion ? "unpin" : "unpin", scrub: -2, markers: false, invalidateOnRefresh: true } }); if (imsvideo.scrollTrigger) { immersiveScrollTriggers.push(imsvideo.scrollTrigger); } //Animation functionlity on scroll for immersive scroll. activate(video, "loadedmetadata", () => { imsvideo.fromTo(video, { currentTime: 0, }, { currentTime: video.duration || 1 }); imsvideo.fromTo(".video-text-container .heading1", { opacity: 0, delay: 1 }, { opacity: 1, ease: "slow", duration: 2 }, 1); imsvideo.to(".video-text-container .heading1", { y: -200, opacity: 0, display: "none", duration: 3 }, "<=+2"); imsvideo.fromTo(".video-text-container .heading2", { y: 150, opacity: 0 }, { opacity: 1, y: 0, duration: 5, delay: 1 }, 5); imsvideo.to(".video-text-container .heading2", { opacity: 0, display: "none", y: -200, duration: 4 }, "<=+5"); imsvideo.fromTo(".right-container .box-heading", { opacity: 0 }, { opacity: 1, duration: 7, delay: 1 }, 13); imsvideo.fromTo(".right-container .box-icons", { opacity: 0 }, { opacity: 1, duration: 7, delay: 3 }, 14); imsvideo.fromTo(".right-container .box-bottom-heading", { opacity: 0 }, { opacity: 1, duration: 6 }, "<=+1"); imsvideo.fromTo(".right-container .description", { opacity: 0 }, { opacity: 1, duration: 6 }, "<=+1"); }); /* When first coded, the Blobbing was important to ensure the browser wasn't dropping previously played segments. Possibly based on memory availability? */ setTimeout(function () { if (window["fetch"]) { fetch(src) .then((response) => response.blob()) .then((response) => { var blobURL = URL.createObjectURL(response); var t = video.currentTime; activate(document.documentElement, "touchstart", function (e) { video.play(); video.pause(); }); video.setAttribute("src", blobURL); video.currentTime = t + 0.01; }); } }, 1000); } else { videoContainer.classList.add("immersive-hide"); rightContainer.classList.remove("immersive-text-hide"); videoText.classList.add("immersive-hide"); reducedMotionImage.classList.remove("immersive-hide"); imsVideo.classList.remove("loaded"); imsReducedAnimation(); } } else { videoText?.classList.add("immersive-hide"); rightContainer.classList.remove("immersive-text-hide"); reducedMotionImage.classList.add("immersive-hide"); imsVideo.classList.remove("loaded"); imsReducedAnimation(); } }); } //function is to stop the animation when reduced motion is on and lower viewports function imsReducedAnimation() { let targets = [".immersive-scroll-video"]; immersiveScrollTriggers?.forEach((trigger) => { trigger.kill(true); let animation = trigger.animation; if (animation) { if (animation.getChildren) { animation.getChildren(true, true, false).forEach(child => { targets = [...targets, ...child.targets()]; }); } else { targets = [...targets, ...animation.targets()]; } } }); gsap.set(targets, { clearProps: "all" }); } //To find the multiple immersive scroll on page to work individually function selectAllImmersiveElements(immersiveOnScroll, isImmersiveAnimate) { for (var i = 0; i < immersiveOnScroll.length; i++) { let videoBg = immersiveOnScroll[i].querySelector(".video-background"), videoAttr = videoBg?.getAttribute("src"); if (videoAttr) { videoAttr.length < 1 ? immersiveOnScroll[i].classList.add("no-video") : immersiveOnScroll[i].classList.add("video"); if (!immersiveOnScroll[i].classList.contains("loaded")) { immersiveOnScroll[i].classList.add("loaded"); isImmersiveAnimate = immersiveOnScroll[i].hasAttribute('immersivescroll-reduced-motion') ? false : isImmersiveAnimate; immersiveVideoOnScroll(immersiveOnScroll[i], videoBg, isImmersiveAnimate); } } else { immersiveOnScroll[i].classList.add("no-video"); if (!immersiveOnScroll[i].classList.contains("loaded")) { immersiveOnScroll[i].classList.add("loaded"); isImmersiveAnimate = immersiveOnScroll[i].hasAttribute('immersivescroll-reduced-motion') ? false : isImmersiveAnimate; immersiveVideoOnScroll(immersiveOnScroll[i], videoBg, isImmersiveAnimate); } } } } //Reduced animation toggle function function immersiveOnReduced(imsOnReduce, isAnimateOnReduce) { for (var k = 0; k < imsOnReduce.length; k++) { imsOnReduce[k].classList.remove("loaded"); imsOnReduce[k].querySelector(".video-container")?.classList.remove("poster-hide"); } selectAllImmersiveElements(imsOnReduce, isAnimateOnReduce); } //Hide poster image on scroll, when video starts playing document.addEventListener('scroll', () => { let imsOnScroll = document.querySelectorAll(".immersive-scroll-video"); let IsAnimateOnScroll = document.body.classList.contains("animation-toggle") ? true : false; for (var i = 0; i < imsOnScroll.length; i++) { if (imsOnScroll[i].getBoundingClientRect().top < 1 && IsAnimateOnScroll === true) { imsOnScroll[i].querySelector(".video-container")?.classList.add("poster-hide"); } } }); //On load DOM event document.addEventListener("DOMContentLoaded", function () { let immersiveOnScroll = document.querySelectorAll(".immersive-scroll-video"); let isImmersiveAnimate = document.body.classList.contains("animation-toggle") ? true : false; //check reduced animation on load selectAllImmersiveElements(immersiveOnScroll, isImmersiveAnimate); document.addEventListener('AEM_ANIMATION_ENABLED', (event) => { if (event.detail == true) { isImmersiveAnimate = true; document.body.classList.add("animation-toggle"); selectAllImmersiveElements(immersiveOnScroll, isImmersiveAnimate); } else { isImmersiveAnimate = false; document.body.classList.remove("animation-toggle"); immersiveOnReduced(immersiveOnScroll, isImmersiveAnimate); } }); }); //** END immersive-scroll-video JS **/