我正在尝试以画布上绘制的圆角矩形的形式创建一个进度条,这个jsfiddle具有以下形状:
this.beginPath();
this.moveTo(x + cornerRadius.upperLeft, y);
this.lineTo(x + width - cornerRadius.upperRight, y);
this.quadraticCurveTo(x + width, y, x + width, y + cornerRadius.upperRight);
this.lineTo(x + width, y + height - cornerRadius.lowerRight);
this.quadraticCurveTo(x + width, y + height, x + width - cornerRadius.lowerRight, y + height);
this.lineTo(x + cornerRadius.lowerLeft, y + height);
this.quadraticCurveTo(x, y + height, x, y + height - cornerRadius.lowerLeft);
this.lineTo(x, y + cornerRadius.upperLeft);
this.quadraticCurveTo(x, y, x + cornerRadius.upperLeft, y);
this.closePath();
有没有简单的方法来绘制这个形状的百分比?或者有一种百分比,其余的是另一种颜色?
我想不出如何做到这一点,除了可能将形状分成4或8块并绘制构成整个形状的每条线或曲线的百分比?像这样但更好:
答案 0 :(得分:7)
您可以像这样绘制圆角矩形的百分比笔划:
完整代码位于底部,这里是一个小提琴:http://jsfiddle.net/m1erickson/P2qTq/
首先定义rect的尺寸。您需要水平和垂直线长以及角半径
// define the rectangle
var horizLineLength=80;
var vertLineLength=40;
var cornerRadius=25;
由于你将逐步抚摸矩形,计算矩形的每个段开始的累积长度。
// calc some lengths for use in percent complete
var cornerLength = 2 * cornerRadius * Math.PI;
var totalLength = cornerLength*4+horizLineLength*2+vertLineLength*2;
// calc at what accumulated length each part of the rect starts
var startT=0; // top line
var startTR=horizLineLength; // top-right corner
var startR=startTR+cornerLength; // right line
var startBR=startR+vertLineLength; // bottom-right corner
var startB=startBR+cornerLength; // bottom line
var startBL=startB+horizLineLength; // bottom-left corner
var startL=startBL+cornerLength; // left line
var startTL=startL+vertLineLength; // top-left corner
然后使用指定的百分比
逐步绘制矩形// incrementally draw the rectangle
// based on the specified percentage
function drawPercentRect(percent){
// use percent to calc the length-traveled-along-rect
accumLength = percent/100 * totalLength;
// clear the canvas
// draw the approprate portion of the top line
// draw the approprate portion of the top-right corner
// draw the approprate portion of the right line
// draw the approprate portion of the bottom-right corner
// draw the approprate portion of the bottom line
// draw the approprate portion of the bottom-left corner
// draw the approprate portion of the left line
// draw the approprate portion of the top-left corner
}
您需要确定要绘制的每个片段的适当长度
对于线条,计算所需线条的长度。如果需要完全绘制线条,请将绘制的线条大小限制为该线条的最大长度。然后绘制从起点到计算终点的线。
// top line
d=accumLength-startT
d=Math.min(d,horizLineLength);
if(d>0){
x1 = offsetX + cornerRadius;
y1 = offsetY;
x2 = offsetX + cornerRadius + d;
y2 = offsetY;
drawLine(x1,y1,x2,y2);
}
对于角点,计算所需弧线的长度。如果需要完全绘制拐角,请将弧形尺寸夹紧到拐角的最大长度。然后绘制扫描从计算的开始扫描到计算结束。
// top-right corner
d=accumLength-startTR;
d=Math.min(d,cornerLength);
if(d>0){
x = offsetX + cornerRadius + horizLineLength;
y = offsetY + cornerRadius;
start = -Math.PI/2;
end = -Math.PI/2 + (d/cornerLength * Math.PI/2) ;
drawCorner(x,y,start,end);
}
以下是完整代码和小提琴:http://jsfiddle.net/m1erickson/P2qTq/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
#slider-vertical{ height:200px; position:absolute; top:60px; left:350px; }
#percent{ width:25px; position:absolute; top:20px; left:340px; border:0; color:blue; font-weight:bold;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// styling
ctx.lineWidth=15;
ctx.strokeStyle="gold";
// define the rectangle
var offsetX=75;
var offsetY=100;
var horizLineLength=80;
var vertLineLength=40;
var cornerRadius=25;
// calc some lengths for use in percent complete
var cornerLength = 2 * cornerRadius * Math.PI;
var totalLength = cornerLength*4+horizLineLength*2+vertLineLength*2;
// calc at what accumulated length each part of the rect starts
var startT=0;
var startTR=horizLineLength;
var startR=startTR+cornerLength;
var startBR=startR+vertLineLength;
var startB=startBR+cornerLength;
var startBL=startB+horizLineLength;
var startL=startBL+cornerLength;
var startTL=startL+vertLineLength;
// percent complete
var percent=100;
// draw the radius rectangle
function drawPercentRect(percent){
// percent expressed as a length-traveled-along-rect
accumLength = percent/100 * totalLength;
// clear the canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
// top line
d=accumLength-startT
d=Math.min(d,horizLineLength);
if(d>0){
x1 = offsetX + cornerRadius;
y1 = offsetY;
x2 = offsetX + cornerRadius + d;
y2 = offsetY;
drawLine(x1,y1,x2,y2);
}
// top-right corner
d=accumLength-startTR;
d=Math.min(d,cornerLength);
if(d>0){
x = offsetX + cornerRadius + horizLineLength;
y = offsetY + cornerRadius;
start = -Math.PI/2;
end = -Math.PI/2 + (d/cornerLength * Math.PI/2) ;
drawCorner(x,y,start,end);
}
// right line
d=accumLength-startR;
d=Math.min(d,vertLineLength);
if(d>0){
x1= offsetX + cornerRadius + horizLineLength + cornerRadius;
y1= offsetY + cornerRadius;
x2= offsetX + cornerRadius + horizLineLength + cornerRadius;
y2= offsetY + cornerRadius + d;
drawLine(x1,y1,x2,y2);
}
// bottom-right corner
d=accumLength-startBR;
d=Math.min(d,cornerLength);
if(d>0){
x = offsetX + cornerRadius + horizLineLength;
y = offsetY + cornerRadius + vertLineLength;
start = 0;
end = (d/cornerLength) * Math.PI/2;
drawCorner(x,y,start,end);
}
// bottom line
d=accumLength-startB;
d=Math.min(d,horizLineLength);
if(d>0){
x1= offsetX + cornerRadius + horizLineLength;
y1= offsetY + cornerRadius + vertLineLength + cornerRadius;
x2 = offsetX + cornerRadius + horizLineLength - d;
y2 = offsetY + cornerRadius + vertLineLength + cornerRadius;
drawLine(x1,y1,x2,y2);
}
// bottom-left corner
d=accumLength-startBL;
d=Math.min(d,cornerLength);
if(d>0){
x = offsetX + cornerRadius;
y = offsetY + cornerRadius + vertLineLength;
start = Math.PI/2;
end = Math.PI/2 + (d/cornerLength) * Math.PI/2;
drawCorner(x,y,start,end);
}
// left line
d=accumLength-startL;
d=Math.min(d,vertLineLength);
if(d>0){
x1= offsetX;
y1= offsetY + cornerRadius + vertLineLength;
x2= offsetX;
y2= offsetY + cornerRadius + vertLineLength - d;
drawLine(x1,y1,x2,y2);
}
// top-left corner
d=accumLength-startTL;
d=Math.min(d,cornerLength);
if(d>0){
x = offsetX + cornerRadius;
y = offsetY + cornerRadius;
start = Math.PI;
end = Math.PI + (d/cornerLength) * Math.PI/2;
drawCorner(x,y,start,end);
}
}
function drawLine(x1,y1,x2,y2){
ctx.beginPath();
ctx.moveTo(x1,y1)
ctx.lineTo(x2,y2);
ctx.stroke();
}
function drawCorner(x,y,start,end){
ctx.beginPath();
ctx.arc(x,y,cornerRadius,start,end,false);
ctx.stroke();
}
// slider for demo
$( "#slider-vertical" ).slider({
orientation: "vertical",
range: "min",
min: 0,
max: 100,
value: 100,
slide: function( event, ui ) {
$( "#percent" ).val( ui.value );
drawPercentRect( ui.value );
}
});
$( "#percent" ).val( $( "#slider-vertical" ).slider( "value" ) );
// draw at 100% to start
drawPercentRect(100);
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
<input type="text" id="percent" />
<div id="slider-vertical"></div>
</body>
</html>