You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

滚动触发序列图动画卡顿,如何预加载541张图片优化体验?

针对541张图片滚动动画的预加载与体验优化方案

一、预加载所有图片的可行实现

可以通过Promise批量追踪图片加载状态,确保所有图片加载完成后再启动动画,彻底避免滚动时出现空白或卡顿:

  1. 改造图片加载逻辑,用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();
});
  1. 配合简单的加载页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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 15:10:39