Lottie on Scroll

by Jon Fuller

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.6.6/lottie.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.5.1/ScrollTrigger.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/35984/ScrollLottie.js"></script>
<div id="animationWindow">
</div>
<div style="background: red; height: 100vh;">
</div>

CSS

body {
 background-color: #0A1045;
}

body,
html {
 height: 100%;
 width: 100%;
 margin: 0;
 padding: 0;
}

#animationWindow {
 width: 100%;
 height: 100%;
 background: black;
}

JavaScript

//ScrollLottie (target: DOMElement string, 
//jsonPath: String, 
//duration: Number, 
//speed: "fast" | "medium" | "slow"
//)

//this has no duration and responds immediately to scroll
/* ScrollLottie({
 target: '#animationWindow',
 path: 'https://cors-anywhere.herokuapp.com/https://freshysites.com/jf-temp/OverscoreIntro.json'
}) */

//this has a duration and animates the playhead on the Lottie animation for a smoother result

const WinScrollLottie = (obj) => {
	let svg_object = document.querySelector(obj.target)


	let anim = lottie.loadAnimation({
		container: svg_object,
		renderer: 'svg',
		loop: false,
		autoplay: false,
		path: obj.path
	});

	let timeObj = {
		currentFrame: 0
	}
	let endString = (obj.speed === "slow") ? "+=2000" : (obj.speed === "medium") ? "+=1000" : (obj.speed === undefined) ? "+=1250" : "+=500";
	ScrollTrigger.create({
		trigger: obj.target,
		scrub: true,
		pin: true,
		start: "top top",
		end: endString,
		onUpdate: self => {
			const blur_px = (0.5 - self.progress) * 20;
			svg_object.style.filter = "blur(" + blur_px + "px)";

			if (obj.duration) {
				gsap.to(timeObj, {
					duration: obj.duration,
					currentFrame: (Math.floor(self.progress * (anim.totalFrames - 1))),
					onUpdate: () => {
						anim.goToAndStop(timeObj.currentFrame, true)
					},
					ease: 'expo'
				})
			} else {
				anim.goToAndStop(self.progress * (anim.totalFrames - 1), true)
			}
		}
	});

}

WinScrollLottie({
	target: '#animationWindow',
	path: 'https://cors-anywhere.herokuapp.com/https://freshysites.com/jf-temp/OverscoreIntro.json',
	duration: .1,
	speed: 'medium'
})