条纹圆形进度条(彩虹色) 实现出来的效果可自定义颜色区间完整代码参考下面(vue2)template div classrainbow-progress-container svg :widthsize :heightsize viewBox0 0 240 240 !-- 底层背景环 -- circle cx120 cy120 r100 fillnone stroke#334155 stroke-opacity0.3 stroke-width24 :stroke-dasharraybgDashArray stroke-linecapbutt /circle !-- 彩虹色条纹环 - 每个条纹根据角度计算颜色 -- g idrainbow-ring circle v-for(block, idx) in coloredBlocks :keyidx cx120 cy120 r100 fillnone :strokeblock.color stroke-width24 :stroke-dasharrayblock.dashArray :stroke-dashoffsetblock.dashOffset stroke-linecapbutt transformrotate(-90 120 120) /circle /g /svg div classtext-center div classpercentage{{ percentage }}%/div h2已完成/h2 /div /div /template script export default { name: RainbowProgress, props: { percentage: { type: Number, default: 70, validator: (val) val 0 val 100, }, size: { type: Number, default: 96, }, radius: { type: Number, default: 100, }, blockCount: { type: Number, default: 40, }, gapSize: { type: Number, default: 6, }, }, computed: { circumference() { return 2 * Math.PI * this.radius; }, blockLength() { return ( (this.circumference - this.blockCount * this.gapSize) / this.blockCount ); }, bgDashArray() { return ${this.blockLength} ${this.gapSize}; }, rainbowColors() { return [ { pos: 0.0, color: [255, 59, 48] }, // 红 #ff3b30 { pos: 0.15, color: [255, 149, 0] }, // 橙 #ff9500 { pos: 0.3, color: [255, 204, 0] }, // 黄 #ffcc00 { pos: 0.45, color: [76, 217, 100] }, // 绿 #4cd964 { pos: 0.6, color: [0, 122, 255] }, // 蓝 #007aff { pos: 0.75, color: [88, 86, 214] }, // 靛 #5856d6 { pos: 0.9, color: [175, 82, 222] }, // 紫 #af52de { pos: 1.0, color: [255, 59, 48] }, // 红 #ff3b30 (回到红色) ]; }, coloredBlocks() { const blocks []; const totalLength this.circumference; for (let i 0; i this.blockCount; i) { const blockStart i * (this.blockLength this.gapSize); const blockCenter (blockStart this.blockLength / 2) / totalLength; const color this.getColorAtPosition(blockCenter); const activeBlocksFloat (this.percentage / 100) * this.blockCount; const isActive i Math.floor(activeBlocksFloat); const isPartial i Math.floor(activeBlocksFloat); const remainderRatio activeBlocksFloat - Math.floor(activeBlocksFloat); const partialLen this.blockLength * remainderRatio; let dashArray, dashOffset; if (isActive) { dashArray ${this.blockLength} ${totalLength - this.blockLength}; dashOffset -blockStart; } else if (isPartial partialLen 0) { dashArray ${partialLen} ${totalLength - partialLen}; dashOffset -blockStart; } else { dashArray 0 ${totalLength}; dashOffset 0; } blocks.push({ color: isActive || (isPartial partialLen 0) ? color : transparent, dashArray: dashArray, dashOffset: dashOffset, }); } return blocks; }, }, methods: { getColorAtPosition(pos) { const colors this.rainbowColors; for (let i 0; i colors.length - 1; i) { const start colors[i]; const end colors[i 1]; if (pos start.pos pos end.pos) { const ratio (pos - start.pos) / (end.pos - start.pos); const r Math.round( start.color[0] (end.color[0] - start.color[0]) * ratio, ); const g Math.round( start.color[1] (end.color[1] - start.color[1]) * ratio, ); const b Math.round( start.color[2] (end.color[2] - start.color[2]) * ratio, ); return rgb(${r}, ${g}, ${b}); } } return rgb(255, 59, 48); }, }, }; /script style scoped .rainbow-progress-container { text-align: center; position: relative; display: inline-block; padding-top: 5px; } .text-center { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100%; } .percentage { font-weight: bold; font-size: 18px; color: #00509a; } h2 { margin: 0; font-size: 14px; color: #64748b; font-weight: normal; letter-spacing: 1px; } /style