自制可配制的canvas进度条,
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>CanvasTest</title> <style type="text/css"> .ProgressBar{ width:300px; } </style> </head> <body> <div class="ProgressBar" currentValue="2600" currentTarget="2200" totalTarget="2500" multiple=1.5 currentTargetShow="true">progress1</div> <div class="ProgressBar" currentValue="2000" currentTarget="2200" totalTarget="2500" multiple=1 currentTargetShow="false">progress2</div> <script> //current value //current target //total target //multiple 进度条长度控制,1为设计长度,小于1为缩小,大于1为加长 //$scale 响应式布局参数 var ProgressBars=document.body.querySelectorAll(".ProgressBar"); for (var i =0 ; i <=ProgressBars.length; i++) { var ProgressBar=ProgressBars[i]; var canvas=document.createElement("canvas"); var currentValue=eval(ProgressBar.getAttribute("currentValue")); var currentTarget=eval(ProgressBar.getAttribute("currentTarget")); var totalTarget=eval(ProgressBar.getAttribute("totalTarget")); var multiple=eval(ProgressBar.getAttribute("multiple")); var currentTargetShow=eval(ProgressBar.getAttribute("currentTargetShow")); var $fontSize=window.getComputedStyle(document.querySelector("body")).fontSize; var $scale= $fontSize.substr(0,$fontSize.length-2)/16; const totalTargetWidth=300*multiple; canvas.width=(160+totalTargetWidth)*$scale; canvas.height=50*$scale; const currentValueWidth=80*$scale;//左侧当前值宽度 const progressHeight=30*$scale;//progress高度 const yStart10=10*$scale; const textStartX=20*$scale; const textStartY=33*$scale; const currentTargetWidth=6*$scale; var currentOutputWidth; var current2TotalTarget=currentValue/totalTarget; var current2CurrentTarget=currentValue/currentTarget; var currentTargetLeft; var extendCurrentTargetWidth=0; var noProductWidth=0; //current value> totalTarget if(current2TotalTarget>=1){ currentOutputWidth=totalTargetWidth*$scale; }else{ //current value< totalTarget if(current2CurrentTarget>=1){ //current value>currentTarget currentOutputWidth=currentTarget/totalTarget*totalTargetWidth*$scale; extendCurrentTargetWidth=(currentValue-currentTarget)/totalTarget*totalTargetWidth*$scale; //noProductWidth=(totalTarget-currentValue)/totalTarget*totalTargetWidth*$scale; }else{//currentValue<currentTarget currentOutputWidth=currentValue/totalTarget*totalTargetWidth*$scale; // extendCurrentTargetWidth=currentOutputWidth; } noProductWidth=(totalTarget-currentValue)/totalTarget*totalTargetWidth*$scale; } currentTargetLeft=currentOutputWidth+currentValueWidth-3*$scale; //current value var ctx=canvas.getContext("2d"); ctx.fillStyle="#dae3f3"; ctx.fillRect(0,yStart10,currentValueWidth,progressHeight); //current value ctx.fillStyle="red";ctx.font="20px 微软雅黑"; ctx.fillText(currentValue,textStartX,33); //current progress ctx.fillStyle="#00b050"; ctx.fillRect(currentValueWidth,yStart10,currentOutputWidth,progressHeight); //extend current ctx.fillStyle="#92d050"; ctx.fillRect(currentValueWidth+currentOutputWidth,yStart10,extendCurrentTargetWidth,progressHeight); //no product——未生产 ctx.fillStyle="#CCC"; ctx.fillRect(currentValueWidth+currentOutputWidth+extendCurrentTargetWidth,yStart10,noProductWidth,progressHeight); //total target ctx.fillStyle="#dae3f3"; ctx.fillRect(canvas.width-currentValueWidth,yStart10,currentValueWidth,progressHeight); ctx.fillStyle="red";ctx.font="20px 微软雅黑"; //total target ctx.fillText(totalTarget,(currentValueWidth*1.25+totalTargetWidth)*$scale,textStartY); //up down rectangle if(currentTargetShow){ ctx.strokeStyle ="blue"; ctx.lineWidth=2; ctx.strokeRect(currentTargetLeft,yStart10/2,currentTargetWidth,yStart10); ctx.strokeRect(currentTargetLeft,yStart10/2*7,currentTargetWidth,yStart10); } ProgressBar.appendChild(canvas); } </script> </body> </html>
其效果图如下:
在此demo中,最重要的一点是利用下述代码查找页面中的 class="ProgressBar"的所有进度条,并利用html的自定义属性存储从后端传递到前端的progress bar参数。
document.body.querySelectorAll(".ProgressBar")
如此前端引用JS 控件就如同写html5原生的标签一样自然,减少冗余代码。
另用svg也可,但svg有一个缺点就是其绘制的图形在html中,css是可以对其进行相应的控制,若选择器使用不佳,对SVG内部会产生影响。但在选择器使用上若能避免滥用的情况下,那么用svg+CSS来实现可配置化,是一个不错的选择。