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

如何让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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:35:32