如何将数值映射至0-1区间?适配ProgressBar进度条库实践
嘿,我来帮你搞定这个进度值映射和代码修改的问题!
核心逻辑:数值映射到0-1区间
根据你的需求,我们需要把delivered - pending的结果映射到0-1的范围,规则是:
- 当
pending=0时,delivered - pending = delivered,此时映射为1(100%进度) - 其他情况,用计算出的进度值除以
delivered(也就是最大可能的进度值),得到0-1之间的小数
公式如下:
// 先计算原始进度值 const rawProgress = delivered - pending; // 处理delivered为0的边界情况,避免除以0 const normalizedProgress = delivered === 0 ? 0 : rawProgress / delivered; // 确保数值不会超出0-1范围(比如rawProgress可能为负或者超过delivered的情况) const clampedProgress = Math.max(0, Math.min(1, normalizedProgress));
代码修改要点
你的代码目前有两个关键问题:
- 异步执行顺序问题:
fetch是异步操作,你现在在fetch外面创建进度条并调用bar.animate,这时候progress还没从API获取到值,会使用未定义的变量。 - 硬编码替换:需要把进度条的文本值和动画参数替换为计算后的归一化进度值。
修改后的完整代码如下:
完整HTML+JS+CSS代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous" ></script> <script src="https://cdn.tutorialjinni.com/progressbar.js/1.1.0/progressbar.js"></script> <style> #progreso { margin: 20px; width: 150px; height: 150px; } </style> </head> <body> <div id="progreso"></div> <script> let delivered, pending, cumplidas; fetch("http://157.230.190.251/api/v1/cmodels/secure/dashboard") .then(function(response) { return response.json(); }) .then(function(json) { console.log(json); cumplidas = json.kpis[0]; delivered = cumplidas.entregadas; pending = cumplidas.pendientes; // 计算归一化的进度值和百分比文本 const rawProgress = delivered - pending; const normalizedProgress = delivered === 0 ? 0 : rawProgress / delivered; const clampedProgress = Math.max(0, Math.min(1, normalizedProgress)); const progressText = Math.round(clampedProgress * 100).toString(); // 创建进度条并执行动画(放到异步回调里,确保拿到数据后再执行) var bar = new ProgressBar.Circle(progreso, { strokeWidth: 6, easing: 'easeInOut', duration: 1400, color: '#FFEA82', trailColor: '#eee', trailWidth: .6, svgStyle: { display: 'block', width: '100%' }, text: { value: progressText, // 替换为计算后的百分比文本 style: { color: '#f00', position: 'absolute', left: '50%', top: '50%', padding: 0, margin: 0, transform: { prefix: true, value: 'translate(-50%, -50%)' } } } }); bar.animate(clampedProgress); // 替换为归一化后的进度值 }) .catch(function(error) { // 处理API请求失败的情况,默认显示0% console.error('Failed to fetch data:', error); var bar = new ProgressBar.Circle(progreso, { strokeWidth: 6, easing: 'easeInOut', duration: 1400, color: '#FFEA82', trailColor: '#eee', trailWidth: .6, svgStyle: { display: 'block', width: '100%' }, text: { value: '0', style: { color: '#f00', position: 'absolute', left: '50%', top: '50%', padding: 0, margin: 0, transform: { prefix: true, value: 'translate(-50%, -50%)' } } } }); bar.animate(0); }); </script> </body> </html>
额外说明
- 边界处理:加入了
delivered=0的判断,避免除以0的错误;同时用Math.max和Math.min确保进度值始终在0-1之间,防止异常数据导致进度条显示异常。 - 异步处理:把进度条的创建和动画触发放到
fetch的then回调里,确保只有当API数据成功返回后才会渲染进度条,避免使用未定义的变量。 - 错误处理:加入了
catch回调,当API请求失败时,进度条会显示0%,提升用户体验。
内容的提问来源于stack exchange,提问作者Julio Rodriguez




