如何修改异步加载的DOM元素?解决JS无法识别异步DOM的问题
解决异步加载Lottie动画DOM元素无法修改的问题
问题出在哪
- 没给动画元素加ID:你写的
<lottie-player>标签少了id="animation",JS里用getElementById根本找不到这个元素 - Shadow DOM挡着了:Lottie Player会把动画放在Shadow DOM里,外部JS直接拿不到内部的DOM节点
- 动画加载慢:动画是异步加载的,你点按钮的时候说不定动画还没渲染完,自然找不到要改的元素
怎么解决
第一步:先把HTML里的动画标签改对
给<lottie-player>加上id="animation",不然JS连元素都摸不着:
<button onclick="myTestFunction()">Change Fill Color</button> <script src="https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js"></script> <lottie-player id="animation" src="https://assets3.lottiefiles.com/packages/lf20_0gfEPCHLKZ.json" background="transparent" speed="1" loop autoplay></lottie-player>
第二步:修改JS代码,绕过Shadow DOM访问元素
改一下myTestFunction,先拿到Shadow DOM里的SVG,再去改颜色:
function myTestFunction() { const player = document.getElementById("animation"); if (!player) { console.error("找不到动画元素"); return; } // 拿到Lottie的Shadow DOM根节点 const shadowRoot = player.shadowRoot; if (!shadowRoot) { console.error("访问不到Shadow DOM"); return; } // 找到内部的SVG元素 const svg = shadowRoot.querySelector("svg"); if (!svg) { console.error("动画还没加载完,再等会儿点"); return; } // 遍历所有<g>元素替换颜色 const gElements = svg.getElementsByTagName("g"); for (let i = 0; i < gElements.length; i++) { gElements[i].innerHTML = gElements[i].innerHTML.replace("rgb(41,37,127)", "#21A73F"); } }
更靠谱的方法:用Lottie官方API改颜色(推荐)
直接改DOM容易被Lottie的重绘覆盖,用官方API改颜色更稳:
function myTestFunction() { const player = document.getElementById("animation"); // 检查动画实例是否初始化完成 if (!player || !player.getLottie()) { alert("动画还在加载,稍等下再点"); return; } const lottie = player.getLottie(); // 把颜色转成Lottie用的RGBA小数数组 const oldColor = [41/255, 37/255, 127/255, 1]; const newColor = [33/255, 167/255, 63/255, 1]; // 遍历所有图层,找到对应颜色的填充层修改 lottie.getLayers().forEach(layer => { if (layer.fill && JSON.stringify(layer.fill.color) === JSON.stringify(oldColor)) { layer.fill.color = newColor; lottie.updateDocumentData(layer, true); } }); // 强制重新渲染 lottie.render(); }
内容的提问来源于stack exchange,提问作者scippy
相关产品推荐
相关产品推荐

