滚动触发序列图动画卡顿,如何预加载541张图片优化体验?
针对541张图片滚动动画的预加载与体验优化方案
一、预加载所有图片的可行实现
可以通过Promise批量追踪图片加载状态,确保所有图片加载完成后再启动动画,彻底避免滚动时出现空白或卡顿:
- 改造图片加载逻辑,用Promise封装每个图片的加载过程
const canvas = document.querySelector(".canvas"); const context = canvas.getContext("2d"); const frameCount = 541; const currentFrame = (index) => `./seq/${(index + 1).toString()}.jpg`; const images = []; let ball = { frame: 0 }; let loadingProgress = 0; // 封装单张图片加载为Promise function loadImage(index) { return new Promise((resolve, reject) => { const img = new Image(); img.src = currentFrame(index); img.onload = () => { loadingProgress++; // 更新加载进度条 document.querySelector(".progress-bar").style.width = `${(loadingProgress / frameCount) * 100}%`; resolve(img); }; img.onerror = reject; }); } // 批量加载所有图片 Promise.all(Array.from({ length: frameCount }, (_, i) => loadImage(i))) .then((loadedImages) => { images.push(...loadedImages); // 所有图片加载完成后初始化动画 initAnimation(); // 隐藏加载页 document.querySelector(".loading-screen").style.display = "none"; }) .catch((err) => console.error("图片加载失败:", err)); function initAnimation() { // 初始化canvas尺寸为第一张图的尺寸 canvas.width = images[0].width; canvas.height = images[0].height; gsap.to(ball, { frame: frameCount - 1, snap: "frame", ease: "none", scrollTrigger: { scrub: true, pin: "canvas", end: "500%", }, onUpdate: render, }); // 首次渲染当前帧 render(); } function render() { context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage(images[ball.frame], 0, 0); } // 监听窗口 resize,保持canvas适配窗口 window.addEventListener("resize", () => { const scale = Math.min(window.innerWidth / images[0].width, window.innerHeight / images[0].height); canvas.width = images[0].width * scale; canvas.height = images[0].height * scale; render(); });
- 配合简单的加载页HTML结构
<!-- 加载页放在canvas之前 --> <div class="loading-screen"> <div class="progress-container"> <div class="progress-bar"></div> </div> <p>加载中...</p> </div> <canvas class="canvas"></canvas>
对应的基础CSS样式:
.loading-screen { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 9999; } .progress-container { width: 60%; height: 4px; background: #eee; margin-bottom: 20px; } .progress-bar { height: 100%; background: #000; width: 0%; transition: width 0.2s ease; }
二、是否需要加载页面?
必须加。541张图片哪怕每张压缩到10KB,总大小也超过5MB,网络环境一般的用户加载时间会在数秒以上。如果跳过加载页,用户滚动到未加载的帧时会出现空白、卡顿甚至动画跳帧,严重破坏体验。加载页能给用户明确的等待反馈,避免用户误以为页面加载失败。
三、额外优化建议
- 优先使用WebP格式图片:WebP比JPG压缩率更高,相同画质下体积可减少30%以上,能大幅缩短加载时间。
- 分批次加载图片:一次性发起541个请求可能触发浏览器请求队列限制,可分批次加载(比如每次加载20张),避免请求拥堵。
- 服务器端缓存优化:设置合适的
Cache-Control缓存头,让用户二次访问时直接从本地缓存读取图片,无需重新加载。
内容的提问来源于stack exchange,提问作者user2599429
相关产品推荐
相关产品推荐

