如何让BodyMovin动画在图片加载完成后启动?(ScrollTrigger场景)
解决方案
方法一:监听BodyMovin的DOMLoaded事件
BodyMovin内置了DOMLoaded事件,会在动画依赖的所有资源(包括图片)加载完成后触发。我们可以通过状态变量控制动画播放时机,确保只有资源就绪后,ScrollTrigger触发时才真正启动动画。
修改后的代码如下:
var ledData = { container: document.getElementById('led-container'), renderer: 'svg', loop: false, autoplay: false, path: '/window.json' }; var ledAnim = bodymovin.loadAnimation(ledData); var isAnimReady = false; // 监听资源加载完成事件 ledAnim.addEventListener('DOMLoaded', function() { isAnimReady = true; }); function playLED () { // 仅在资源就绪时播放动画 if (isAnimReady) { ledAnim.play(); ledAnim.setDirection(1); ledAnim.setSpeed(20); } } ScrollTrigger.create({ trigger: ".container", markers: true, start: "top", scrub: true, pin: true, onEnter: playLED, })
如果想在资源加载完成后,自动补播已经错过的触发时机,可以在DOMLoaded回调中增加滚动位置判断:
ledAnim.addEventListener('DOMLoaded', function() { isAnimReady = true; // 检查容器是否已进入触发区域 var triggerElement = document.querySelector('.container'); var rect = triggerElement.getBoundingClientRect(); if (rect.top <= 0) { playLED(); } });
方法二:手动预加载动画中的图片资源
如果需要更精细的加载控制(比如显示加载进度),可以从动画JSON文件中提取所有图片路径,手动完成预加载后再初始化动画。
示例代码:
// 先请求动画配置JSON fetch('/window.json') .then(response => response.json()) .then(animJson => { // 提取所有图片资源的完整路径 const imagePaths = animJson.assets .filter(asset => asset.type === 'image') .map(asset => asset.u + asset.p); // 批量预加载图片的工具函数 function preloadImages(paths) { return Promise.all(paths.map(path => { return new Promise((resolve, reject) => { const img = new Image(); img.src = path; img.onload = resolve; img.onerror = reject; }); })); } // 所有图片加载完成后初始化动画 preloadImages(imagePaths).then(() => { var ledData = { container: document.getElementById('led-container'), renderer: 'svg', loop: false, autoplay: false, animationData: animJson // 直接传入已加载的JSON,避免重复请求 }; var ledAnim = bodymovin.loadAnimation(ledData); function playLED () { ledAnim.play(); ledAnim.setDirection(1); ledAnim.setSpeed(20); } ScrollTrigger.create({ trigger: ".container", markers: true, start: "top", scrub: true, pin: true, onEnter: playLED, }); }).catch(err => { console.error('图片预加载失败:', err); // 加载失败时可做降级处理,比如直接启动动画 }); });
方案对比
- 方法一简洁高效,利用BodyMovin内置事件,适合绝大多数场景。
- 方法二适合需要自定义加载逻辑的场景,比如添加加载状态提示。
内容的提问来源于stack exchange,提问作者Eniso
相关产品推荐
相关产品推荐

