
页面加载后 Canvas 动画不显示,仅在滚动触发 ScrollTrigger 后才出现;根本原因是 render() 未在初始加载时调用,需在 DOM 就绪且资源加载完成后主动执行首次绘制。
页面加载后 canvas 动画不显示,仅在滚动触发 scrolltrigger 后才出现;根本原因是 render() 未在初始加载时调用,需在 dom 就绪且资源加载完成后主动执行首次绘制。
要解决 GSAP 滚动驱动的帧序列动画在页面初次加载时不渲染的问题,关键在于确保 render() 函数在图像加载完成、Canvas 尺寸初始化完毕后立即执行一次——而非仅依赖 ScrollTrigger 的 onUpdate 触发。
当前代码中,render() 仅在 gsap.to().onUpdate 和 resize 事件中被调用,而 window.onload 或 DOMContentLoaded 并未触发绘制,导致首屏空白。此外,imagesLoaded === frameCount 回调中虽调用了 render(),但此时 Canvas 尺寸可能尚未按视口正确设置(尤其在高 DPI 设备或动态布局下),造成渲染异常或不可见。
✅ 正确做法是:将初始化逻辑(尺寸设置 + 首帧绘制)抽离为独立函数,并在多个时机统一调用:
function setup() {
// 确保 canvas 尺寸与当前视口匹配
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 强制绘制当前帧(imageSeq.frame 默认为 0)
render();
}
// 页面加载完成时执行(含图片等资源)
window.addEventListener('load', setup);
// 窗口大小变化时响应(防抖优化版)
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(setup, 16); // ~60fps 节流
});
// 同时保留原有图片加载完成后的兜底调用(增强鲁棒性)
if (imagesLoaded === frameCount) {
setup(); // 替代原 render(),确保尺寸+绘制同步
}
⚠️ 注意事项:
- 不要直接写
window.onload = setup()(带括号会立即执行),应为window.onload = setup(传递函数引用); -
window.addEventListener('load', setup)更现代、支持多监听器,推荐替代onload赋值; -
resize事件高频触发,务必加节流(如setTimeout或requestAnimationFrame),避免重绘风暴; - 若使用
scrollTrigger: { start: 'left %' },请确认.header__list-item.message元素真实存在且可计算位置,否则触发器失效可能导致动画静默; - 建议为 Canvas 添加临时背景色(如
ctx.fillStyle = '#f0f0f0'; ctx.fillRect(0,0,canvas.width,canvas.height);)便于调试是否真的未绘制。
最终,通过 setup() 统一管控尺寸与首帧渲染,配合 GSAP 的 scrub: 1 平滑插值,即可实现:页面加载即可见初始帧 → 滚动实时播放 → 回滚精准倒播,达成专业级帧动画体验。











