如何将JavaScript计算的百分比值传入CSS动画中?
问题描述
我需要将JavaScript计算得到的百分比值c2_percent传入CSS动画show-bar-eight中,替换该动画100%关键帧里的固定30%值,让条形图能从0扩展到计算出的对应比例。
现有代码
HTML结构
<div class="bar-graph bar-graph-horizontal bar-graph-one"> <div class="bar-one"> <span class="rating-a1">A1</span> <div class="bar" id="rating-a1" data-percentage=""></div> </div> <div class="bar-two"> <span class="rating-a2">A2</span> <div class="bar" data-percentage="11%"></div> </div> <div class="bar-three"> <span class="rating-a3">A3</span> <div class="bar" data-percentage="7%"></div> </div> <div class="bar-four"> <span class="rating-b1">B1</span> <div class="bar" data-percentage="10%"></div> </div> <div class="bar-five"> <span class="rating-b2">B2</span> <div class="bar" data-percentage="20%"></div> </div> <div class="bar-six"> <span class="rating-b3">B3</span> <div class="bar" data-percentage="5%"></div> </div> <div class="bar-seven"> <span class="rating-c1">C1</span> <div class="bar" data-percentage="9%"></div> </div> <div class="bar-eight"> <span class="rating-c2">C2</span> <div class="bar" id="c2-rating" data-percentage=""></div> </div> <div class="bar-nine"> <span class="rating-c3">C3</span> <div class="bar" data-percentage="5%"></div> </div> <div class="bar-ten"> <span class="rating-d1">D1</span> <div class="bar" data-percentage="5%"></div> </div> </div>
CSS动画
@-webkit-keyframes show-bar-eight { 0% { width: 0; } 100% { width: 30%; } }
JavaScript计算逻辑
for(let i = 0; i < 1; i++) { const c2_security_values = Array.from(document.querySelectorAll('.security-value-c2')); const c2_security_values_inner = c2_security_values.map((element) => element.innerText); const c2_summed_values = c2_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue)); const total_security_values = Array.from(document.querySelectorAll('.individual-market-value')); const total_security_values_inner = total_security_values.map((element) => element.innerText); const total_summed_values = total_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue)); const c2_percent = c2_summed_values / total_summed_values }
解决方案
方法一:使用CSS自定义属性(推荐)
这是最灵活且易维护的方案,通过CSS变量动态传递计算值:
- 修改CSS动画,用变量替代固定值:
@-webkit-keyframes show-bar-eight { 0% { width: 0; } 100% { width: var(--target-width, 30%); /* 30%作为降级默认值 */ } } @keyframes show-bar-eight { /* 补充标准写法兼容非webkit浏览器 */ 0% { width: 0; } 100% { width: var(--target-width, 30%); } } /* 给条形图绑定动画类 */ .bar.show-bar-animation { -webkit-animation: show-bar-eight 1s forwards; animation: show-bar-eight 1s forwards; }
- 修改JavaScript,计算后设置变量并触发动画:
for(let i = 0; i < 1; i++) { const c2_security_values = Array.from(document.querySelectorAll('.security-value-c2')); const c2_security_values_inner = c2_security_values.map((element) => element.innerText); const c2_summed_values = c2_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue)); const total_security_values = Array.from(document.querySelectorAll('.individual-market-value')); const total_security_values_inner = total_security_values.map((element) => element.innerText); const total_summed_values = total_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue)); const c2_percent = (c2_summed_values / total_summed_values) * 100; // 转换为百分比数值 const c2Bar = document.getElementById('c2-rating'); // 设置CSS变量 c2Bar.style.setProperty('--target-width', `${c2_percent}%`); // 更新data-percentage属性 c2Bar.setAttribute('data-percentage', `${c2_percent.toFixed(1)}%`); // 添加动画类触发动画 c2Bar.classList.add('show-bar-animation'); }
方法二:动态创建CSS样式规则
如果需要兼容不支持CSS变量的旧浏览器,可以用JS动态生成动画规则:
for(let i = 0; i < 1; i++) { // 保留原计算逻辑 const c2_security_values = Array.from(document.querySelectorAll('.security-value-c2')); const c2_security_values_inner = c2_security_values.map((element) => element.innerText); const c2_summed_values = c2_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue)); const total_security_values = Array.from(document.querySelectorAll('.individual-market-value')); const total_security_values_inner = total_security_values.map((element) => element.innerText); const total_summed_values = total_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue)); const c2_percent = (c2_summed_values / total_summed_values) * 100; // 创建动态样式 const style = document.createElement('style'); style.textContent = ` @-webkit-keyframes show-bar-eight { 0% { width: 0; } 100% { width: ${c2_percent}%; } } @keyframes show-bar-eight { 0% { width: 0; } 100% { width: ${c2_percent}%; } } #c2-rating { -webkit-animation: show-bar-eight 1s forwards; animation: show-bar-eight 1s forwards; } `; document.head.appendChild(style); // 更新data-percentage属性 document.getElementById('c2-rating').setAttribute('data-percentage', `${c2_percent.toFixed(1)}%`); }
方法三:纯JavaScript控制动画
完全不用CSS关键帧,用requestAnimationFrame手动控制宽度变化:
for(let i = 0; i < 1; i++) { // 保留原计算逻辑 const c2_security_values = Array.from(document.querySelectorAll('.security-value-c2')); const c2_security_values_inner = c2_security_values.map((element) => element.innerText); const c2_summed_values = c2_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue)); const total_security_values = Array.from(document.querySelectorAll('.individual-market-value')); const total_security_values_inner = total_security_values.map((element) => element.innerText); const total_summed_values = total_security_values_inner.reduce((accumulator, currentValue) => parseInt(accumulator) + parseInt(currentValue)); const c2_percent = (c2_summed_values / total_summed_values) * 100; const c2Bar = document.getElementById('c2-rating'); const targetWidth = c2_percent; const duration = 1000; // 动画时长1秒 let startTime; function animate(timestamp) { if (!startTime) startTime = timestamp; const elapsed = timestamp - startTime; const progress = Math.min(elapsed / duration, 1); c2Bar.style.width = `${progress * targetWidth}%`; if (progress < 1) { requestAnimationFrame(animate); } else { c2Bar.setAttribute('data-percentage', `${targetWidth.toFixed(1)}%`); } } requestAnimationFrame(animate); }
内容的提问来源于stack exchange,提问作者evan2160
相关产品推荐
相关产品推荐

