如何在环形进度条统计模块中支持浮点数值?
如何在环形进度条统计模块中支持浮点数值?
嘿,我一眼就瞅出问题所在啦!你当前的代码里用progressStartValue++每次让数值加1,这对整数没问题,但碰到99.9这种小数时,这个变量永远只会是整数,根本到不了目标的浮点值,再加上用==判断浮点数相等(本身就容易有精度坑),定时器自然停不下来啦。咱们来改几处就能解决:
核心问题分析
- 整数递增逻辑:
progressStartValue++只能生成整数,永远追不上99.9这种浮点目标值; - 浮点数相等判断:直接用
==比较浮点数,会因为JS的浮点精度问题永远无法匹配(比如0.1+0.2≠0.3); - 数值显示精度:浮点运算可能产生多余的小数位,影响显示效果。
修改方案
把定时器里的代码改成下面这样,我给你标了关键修改点:
let progress = setInterval(() => { // 1. 改成每次增加0.1,适配浮点数值(步长可根据动画速度调整) progressStartValue += 0.1; // 2. 格式化显示数值,避免精度问题导致的奇怪小数位 // 这里判断如果目标是整数就显示整数,否则显示一位小数 const displayValue = Number.isInteger(progressEndValue) ? progressStartValue.toFixed(0) : progressStartValue.toFixed(1); progressValue.textContent = displayValue; circularProgress.style.background = `conic-gradient(#099bf0, #7cbf3d,#00b3cf, #1f58f2, #5618d4 ${progressStartValue * 3.6}deg, #EAEAEC 0deg)`; // 3. 改用范围判断,避免浮点数相等的精度坑 if (progressStartValue >= progressEndValue - 0.05) { // 4. 最后强制设置为目标值,保证显示和进度条完全准确 progressValue.textContent = Number.isInteger(progressEndValue) ? progressEndValue.toFixed(0) : progressEndValue.toFixed(1); circularProgress.style.background = `conic-gradient(#099bf0, #7cbf3d,#00b3cf, #1f58f2, #5618d4 ${progressEndValue * 3.6}deg, #EAEAEC 0deg)`; clearInterval(progress); } }, speed);
额外说明
- 步长调整:你可以修改
0.1这个步长,比如改成0.05动画会更平滑,但动画时长会变长;改成0.2则更快,根据需求调整就行; - 为什么
parseInt没用:parseInt(99.9)会直接把小数转成99,虽然能让定时器停止,但丢失了你想要保留的小数信息,所以不是正确的解决方案; - 精度误差处理:判断时用
progressStartValue >= progressEndValue - 0.05是给浮点运算留了一点误差空间,确保能触发停止逻辑。
修改后的完整JS代码
const statContainer = document.querySelectorAll(".stat-container"); const options = { root: null, threshold: 0, rootMargin: "-150px" }; const observer = new IntersectionObserver(function(entries, observer) { entries.forEach(entry => { if (!entry.isIntersecting) { return; } let container = entry.target; let circularProgress = container.querySelector(".circular-progress"), progressValue = container.querySelector(".progress-value"); let progressEndValue = parseFloat(progressValue.innerText), speed = 1; // 初始值设为0.0更清晰,JS数字类型不影响,但语义更明确 let progressStartValue = 0.0; console.log(progressEndValue); let progress = setInterval(() => { progressStartValue += 0.1; const displayValue = Number.isInteger(progressEndValue) ? progressStartValue.toFixed(0) : progressStartValue.toFixed(1); progressValue.textContent = displayValue; circularProgress.style.background = `conic-gradient(#099bf0, #7cbf3d,#00b3cf, #1f58f2, #5618d4 ${progressStartValue * 3.6}deg, #EAEAEC 0deg)`; if (progressStartValue >= progressEndValue - 0.05) { progressValue.textContent = Number.isInteger(progressEndValue) ? progressEndValue.toFixed(0) : progressEndValue.toFixed(1); circularProgress.style.background = `conic-gradient(#099bf0, #7cbf3d,#00b3cf, #1f58f2, #5618d4 ${progressEndValue * 3.6}deg, #EAEAEC 0deg)`; clearInterval(progress); } }, speed); observer.unobserve(entry.target); }) }, options); statContainer.forEach(stat => { observer.observe(stat); });
原始CSS(无需修改)
/* Start of Stat Styling */ .stat-container { align-items: center; display: flex; flex-direction: column; row-gap: 30px; } /* Controls Color of the Ring */ .circular-progress { display: flex; align-items: center; justify-content: center; position: relative; height: 200px; width: 200px; border-radius: 50%; background: conic-gradient(#5618d4, #1f58f2, #099bf0, #00b3cf, #7cbf3d 0deg, #EAEAEC 0deg); } /* Controls Color Inside of the Ring */ .circular-progress::before { content: ""; position: absolute; height: 180px; width: 180px; border-radius: 50%; background-color: #FFFFFF; } .progress-value { background: -webkit-linear-gradient(360deg, #5618D4, #1F58F2, #099BF0); -webkit-background-clip: text; -webkit-text-fill-color: transparent; position: relative; font-size: 3.875rem; line-height: 3.875rem; } .progress-value:after { content: "%"; } .text { color: #060F42; font-size: 1.5rem; line-height: 2.125rem; letter-spacing: -0.24px; max-width: 582px; width: 100%; text-align: center; } /* End of Stat Styling */
原始HTML(无需修改)
<div> <div class="stat-container"> <div class="circular-progress"> <span class="progress-value">99.9</span> </div> <span class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</span> </div> <div class="stat-container"> <div class="circular-progress"> <span class="progress-value">70</span> </div> <span class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</span> </div> <div class="stat-container"> <div class="circular-progress"> <span class="progress-value">99</span> </div> <span class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</span> </div> </div>
这样不管是整数还是小数,进度条都能正常走完并准确停止啦!
备注:内容来源于stack exchange,提问作者rnkwill
相关产品推荐
相关产品推荐

