带有圆角的画布矩形作为进度条? [英] Canvas rectangle with rounded corners as a progress bar?

查看:134
本文介绍了带有圆角的画布矩形作为进度条?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在画布上绘制一个圆角矩形形式的进度条,这个jsfiddle的形状:





首先定义rect的尺寸。您需要水平和垂直线长度和角半径

  //定义矩形
var horizLineLength = 80;
var vertLineLength = 40;
var cornerRadius = 25;

由于您将逐渐抚摸直线,计算每段矩形开始的累计长度。

  //计算一些长度用于完成百分比
var cornerLength = 2 * cornerRadius * Math.PI;
var totalLength = cornerLength * 4 + horizLineLength * 2 + vertLineLength * 2;

//计算rect的每个部分的累计长度
var startT = 0; // top line
var startTR = horizLineLength; //右上角
var startR = startTR + cornerLength; // right line
var startBR = startR + vertLineLength; //右下角
var startB = startBR + cornerLength; // bottom line
var startBL = startB + horizLineLength; //左下角
var startL = startBL + cornerLength; // left line
var startTL = startL + vertLineLength; // top-left corner

然后使用指定的百分比递增绘制rect

  //根据指定的百分比递增绘制矩形
//
函数drawPercentRect(percent){

//使用百分比来计算length-traveled-along-rect
accumLength = percent / 100 * totalLength;

//清除画布
//绘制顶行的合适部分
//绘制右上角的合适部分
//绘制右边线的合适部分
//绘制右下角的合适部分
//绘制底线的合适部分
//绘制底部的合适部分-left corner
//绘制左边线的合适部分
//绘制左上角的合适部分
}

您需要确定要绘制的每个段的适当长度



的线路需要。如果线需要完全绘制,请将绘制的线大小钳制到该线的最大长度。

  //顶行
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);
}

对于角,计算所需的弧的长度。如果角需要完全拉伸,则将弧度大小钳位到角的最大长度。然后从计算开始到计算结束绘制弧线扫描。

  //右上角
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 =stylesheettype =text / cssmedia =allhref =css / reset.css/> <! - reset css - >
< link rel =stylesheethref =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;颜色:蓝色; font-weight:bold;}
< / style>

< script>
$(function(){

var canvas = document.getElementById(canvas);
var ctx = canvas.getContext(2d);

// styleing
ctx.lineWidth = 15;
ctx.strokeStyle =gold;

//定义矩形
var offsetX = 75 ;
var offsetY = 100;
var horizLineLength = 80;
var vertLineLength = 40;
var cornerRadius = 25;

//计算一些长度用于完成百分比
var cornerLength = 2 * cornerRadius * Math.PI;
var totalLength = cornerLength * 4 + horizLineLength * 2 + vertLineLength * 2;

$ b b //计算矩形开始的每个部分的累积长度
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;

//完成百分比
var percent = 100;

//绘制半径矩形
function drawPercentRect(percent){

//百分比表示为length-traveled-along-rect
accumLength = percent / 100 * totalLength;

//清除画布
ctx.clearRect(0,0,canvas.width,canvas.height);

//顶行
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);
}

//右上角
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);
}

//右行
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);
}

//右下角
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);
}

//底行
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);
}

//左下角
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);
}

//左上角
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();
}

函数drawCorner(x,y,start,end){
ctx.beginPath();
ctx.arc(x,y,cornerRadius,start,end,false);
ctx.stroke();
}


//演示的滑块
$(#slider-vertical).slider({

orientation:垂直,
范围:min,
min:0,
max:100,
值:100,
幻灯片:function(event,ui){
$(#percent).val(ui.value);
drawPercentRect(ui.value);
}
});

$(#percent).val($(#slider-vertical).slider(value));

//绘制在100%开始
drawPercentRect(100);


}); // end $(function(){});
< / script>

< / head>

< body>
< canvas id =canvaswidth = 300 height = 300>< / canvas>
< input type =textid =percent/>
< div id =slider-vertical>< / div>
< / body>
< / html>


I'm trying to make a progress bar in the form of a rounded rectangle drawn on canvas, this jsfiddle has the shape:

http://jsfiddle.net/xT3ax/

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();

Is there any easy way to draw a percentage of this shape only? or have a percentage one colour and the rest another?

I can't think of how to do this except maybe break the shape into 4 or 8 pieces and draw a percentage of each line or curve that makes up the entire shape? like this but better:

http://jsfiddle.net/xT3ax/1/

解决方案

You can draw the percentage-stroke of rounded rectangle like this:

Full code is at the bottom and here is a Fiddle: http://jsfiddle.net/m1erickson/P2qTq/

First define the dimensions of the rect. You need the horizontal and vertical line lengths and corner radius

// define the rectangle
var horizLineLength=80;
var vertLineLength=40;
var cornerRadius=25;

Since you will be stroking the rect incrementally, calculate at what accumulated length each segment of the rect will begin.

// 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

Then incrementally draw the rect using the specified percentage

// 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
}

You need to determine the appropriate length of each segment to draw

For lines, calculate the length of that line needed. If the line needs to be fully drawn, clamp the line size drawn to the maximum length of that line. Then draw the line from the starting point to the calculated end point.

    // 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);
    }

For corners, calculate the length of that arc needed. If the corner needs to be fully drawn, clamp the arc size to the maximum length of the corner. Then draw the arc sweeping from the calculated start to calculated end.

    // 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);    
    }

Here is full code and a Fiddle: 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>

这篇关于带有圆角的画布矩形作为进度条?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆