UNPKG

canvas-scroll-clip

Version:

Canvas based image sequence scroll animation. Zero dependencies.

307 lines (265 loc) 6.21 kB
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title>csc.js</title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;400;700&display=swap" rel="stylesheet"> <style> :root { --color-white: #fff; --font-weight-bold: 700; } *, :after, :before { box-sizing: border-box; -webkit-backface-visibility: hidden; backface-visibility: hidden; } html { padding: 0; margin: 0; font-size: 16px; background-color: #000; margin: 0; padding: 0; } body { min-height: 100%; height: auto; margin: 0; padding: 0; font-family: 'Roboto', sans-serif; overscroll-behavior-y: none; overflow-x: hidden; position: relative; } @-webkit-keyframes ani-mouse { 0% { opacity: 1; top: 20%; } 20% { opacity: 1; top: 30%; } 70% { opacity: 0.5; top: 40%; } 100% { opacity: 0; top: 20%; } } @-moz-keyframes ani-mouse { 0% { opacity: 1; top: 20%; } 20% { opacity: 1; top: 30%; } 70% { opacity: 0.5; top: 40%; } 100% { opacity: 0; top: 20%; } } @keyframes ani-mouse { 0% { opacity: 1; top: 20%; } 20% { opacity: 1; top: 30%; } 70% { opacity: 0.5; top: 40%; } 100% { opacity: 0; top: 20%; } } @-webkit-keyframes ani-loader { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @-moz-keyframes ani-loader { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes ani-loader { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .scroll-indicator { letter-spacing: 1px; font-size: 10px; position: fixed; left: 0; right: 0; bottom: 50px; margin: 0 auto; color: #fff; text-align: center; text-transform: uppercase; z-index: 100; } .scroll-indicator .scroll-indicator-icon { position: relative; display: block; width: 35px; height: 55px; margin: 0 auto 20px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; border: 3px solid var(--color-white); border-radius: 23px; } .scroll-indicator .scroll-indicator-icon::before { content: ""; position: absolute; display: block; top: 20%; left: 50%; width: 4px; margin-left: -2px; height: 12px; background: var(--color-white); border-radius: 6px; -webkit-animation: ani-mouse 2s linear infinite; -moz-animation: ani-mouse 2s linear infinite; animation: ani-mouse 2s linear infinite; } .promo { color: var(--color-white); font-size: 3rem; opacity: 0; position: absolute; bottom: 250px; left: 50%; transform: translateX(-50%); z-index: 2; transition: opacity 300ms ease-in-out; font-weight: var(--font-weight-bold); } .promo.loaded { opacity: 1; } .dummy-content { display: block; width: 100%; height: 500px; } /* CanvasScrollClip - required */ .container { position: relative; } /* .csc-container { min-height: 100%; position: relative; } */ .csc { height: 100vh; width: 100%; position: sticky; top: 0; display: flex; align-items: center; justify-content: center; z-index: 1; padding: 5rem; } .csc-canvas { display: block; max-width: 100%; max-height: 100%; object-fit: contain; position: relative; z-index: 1; opacity: 0; transition: opacity 300ms ease-in-out; } .csc--loaded .csc-canvas { opacity: 1; } /* Loader - optional */ .csc::after { content: " "; display: block; width: 50px; height: 50px; margin: 8px; border-radius: 50%; border: 6px double var(--color-white); border-color: var(--color-white) transparent var(--color-white) transparent; animation: ani-loader 1.2s linear infinite; position: absolute; top: 50%; transform: translateY(-50%); transition: opacity 300ms ease-in-out; opacity: 0.6; z-index: 2; } .csc--loaded .csc::after { display: none; } </style> </head> <body> <div class="dummy-content"></div> <div class="container"> <div class="canvas-container"></div> <div class="promo">enjoy!</div> </div> <div class="scroll-indicator"> <span class="scroll-indicator-icon"></span> <span>scroll down</span> </div> <script type="module"> import CSC from "./js/main.js"; const element = document.querySelector('.canvas-container'); const options = { framePath: "https://www.apple.com/105/media/us/airpods-pro/2019/1299e2f5_9206_4470_b28e_08307a42f19b/anim/sequence/large/01-hero-lightpass/0001.jpg", frameCount: 140, scrollArea: 2000 }; window.addEventListener("DOMContentLoaded", function () { const csc = new CSC(element, options); csc.events.on('viewport.scroll', (scrollTop) => { const element = document.querySelector('.promo'); const screenHeight = window.innerHeight; const when = document.documentElement.scrollHeight - innerHeight - 200; if (scrollTop >= when) { element.style.setProperty("opacity", "1"); } else { element.style.removeProperty('opacity'); } }); }); </script> </body> </html>