如何在JavaScript路径变形时保留SVG样式(颜色)?
问题描述
我正在开发一个动画地图,包含23个图标,用户滚动页面时,图标会从红白警报信号变形为对应颜色的对话气泡。变形动画运行正常,但SVG中指定的颜色无法在动画过程中同步生效。我需要红色警报图标在滚动时,颜色随变形进度逐渐过渡到对话气泡路径指定的橙色/蓝色等,变形完成时颜色也同步切换完成。
现有样式代码
.st0{fill:#FFCA19;stroke:#FFFFFF;stroke-miterlimit:10;} .st1{fill:#FFFFFF;} .st2{fill:#279CD7;} .st3{fill:#E44D25;} .st4{fill:#E1A6CA;} .st5{fill:#F68C22;} .st6{fill:#3B2F8F;} .st7{fill:#70BE54;}
图标集示例(23个之一)
<g id="iconset1"> <path id="bub1" d="M83.5 110.2c0-7.6-6.1-13.7-13.7-13.7s-13.7 6.1-13.7 13.7 6.1 13.7 13.7 13.7h.8l-1.5 3.7 9-6.4c3.3-2.5 5.4-6.5 5.4-11z" class="st2"/> <path id="altbg1" d="M76.7 118.1H62.9c-1.1 0-2-.6-2.6-1.5-.5-.9-.5-2 0-3l6.9-11.9c.5-.9 1.5-1.5 2.6-1.5s2 .6 2.6 1.5l6.9 11.9c.5.9.5 2 0 3-.6 1-1.6 1.5-2.6 1.5z" class="st1"/> <path id="alt1" d="m79.3 113.5-6.9-11.9c-.6-.9-1.5-1.5-2.6-1.5s-2.1.6-2.6 1.5l-6.9 11.9c-.5 1-.5 2.1 0 3 .6.9 1.5 1.5 2.6 1.5h13.8c1 0 2-.5 2.6-1.5.5-1 .5-2 0-3zm-7.9 1.8h-3.2v-2.9h3.2v2.9zm.1-9.4c0 1.4-.7 5.1-.7 5.5h-2c0-.3-.7-4.1-.7-5.4v-1.8h3.4v1.7z" class="st3"/> </g>
现有CSS代码
.container { position: absolute; margin-left: auto; margin-right: auto; left: 0; right: 0; div-align: center; height: 80%; } [id^="bub"] { visibility: hidden; } body { background-color: lightblue; }
现有JS代码
let main_tl = []; let iconmorphComplete = []; let animationStarted = false; function iconmorph(altSelector, bubSelector) { let tl = new TimelineMax(); let s_tl = new TimelineMax(); tl.to(altSelector, 3, {morphSVG: bubSelector}, "start"); tl.eventCallback("onComplete", function() { iconmorphComplete[altSelector] = true; }); return tl; } function handleScroll() { const scrollPercentage = (window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100; if (scrollPercentage >= 0 && !animationStarted) { for (let i = 1; i <= 23; i++) { const altSelector = "#alt" + i; const bubSelector = "#bub" + i; main_tl[altSelector] = iconmorph(altSelector, bubSelector); animationStarted = true; } } if (animationStarted) { for (let i = 1; i <= 23; i++) { const altSelector = "#alt" + i; const progress = (scrollPercentage - 0) / (120 - 0); if (!iconmorphComplete[altSelector]) { main_tl[altSelector].progress(progress).pause(); } } } } window.addEventListener('scroll', handleScroll);
已尝试但无效的修改
尝试1
function iconmorph(altSelector, bubSelector) { let tl = new TimelineMax(); let s_tl = new TimelineMax(); tl.set(altSelector, { fill: 'currentColor' }); tl.set(bubSelector, { fill: 'currentColor' }); tl.to(altSelector, 3, { morphSVG: bubSelector }, "start"); tl.eventCallback("onComplete", function() { iconmorphComplete[altSelector] = true; }); return tl; }
尝试2
function iconmorph(altSelector, bubSelector) { let tl = new TimelineMax(); let s_tl = new TimelineMax(); const altColor = $(altSelector).attr('fill'); tl.set(altSelector, { fill: altColor }); tl.set(bubSelector, { fill: 'currentColor' }); tl.to(altSelector, 3, { morphSVG: bubSelector }, "start"); tl.to(altSelector, 3, { fill: 'currentColor' }, "start"); tl.to(bubSelector, 3, { fill: altColor }, "start"); tl.eventCallback("onComplete", function() { iconmorphComplete[altSelector] = true; }); return tl; }
解决方案
问题核心是需正确获取目标气泡的实际填充色,同步执行颜色过渡与变形动画,同时规避CSS类与内联样式的优先级冲突。
修改iconmorph函数如下:
function iconmorph(altSelector, bubSelector) { let tl = new TimelineMax(); // 获取警报图标的初始计算颜色(从CSS类提取,而非内联属性) const altEl = document.querySelector(altSelector); const altColor = getComputedStyle(altEl).fill; // 获取目标气泡的计算颜色 const bubEl = document.querySelector(bubSelector); const bubColor = getComputedStyle(bubEl).fill; // 同步执行变形与颜色过渡动画 tl.to(altSelector, 3, { morphSVG: bubSelector, fill: bubColor // 随变形进度过渡到气泡颜色 }, "start"); tl.eventCallback("onComplete", function() { iconmorphComplete[altSelector] = true; // 动画完成后隐藏警报背景,显示气泡 const iconIndex = altSelector.slice(-1); document.querySelector(`#altbg${iconIndex}`).style.visibility = 'hidden'; bubEl.style.visibility = 'visible'; }); return tl; }
同时调整气泡的CSS可见性设置,避免影响颜色获取:
[id^="bub"] { visibility: hidden; position: absolute; /* 防止布局偏移 */ }
关键说明
- 使用
getComputedStyle获取元素实际渲染的颜色,而非直接读取fill属性,因为颜色由CSS类定义而非内联属性。 - 在同一个动画步骤中同时指定
morphSVG和fill属性,确保变形与颜色过渡进度完全同步。 - 动画完成后切换元素可见性,保证最终显示目标气泡图标。
内容的提问来源于stack exchange,提问作者BobSaget
相关产品推荐
相关产品推荐

