Javascript 进度条动画

Javascript 进度条动画,javascript,jquery,html,canvas,Javascript,Jquery,Html,Canvas,我想创建一个进度条,它遵循jquery示例中概述的代码路径: Jsfiddle: 我如何将此条设置为百分比/进度条的动画?它从左下角开始为红色,逆时针旋转。我见过各种各样的例子,但我无法实现它们,因为它们是基于使用pi或直线的径向例子 我基本上希望根据百分比设置绘制路径的动画 在此方面的任何帮助都将不胜感激。@gamealchest有一个很好的简化想法,即在每一侧使用半圆,而不是Q曲线。这是因为圆的周长很容易计算:2*PI*半径。Q曲线的周长更难计算:在曲线上绘制100多个点,并测量这些点所覆盖

我想创建一个进度条,它遵循jquery示例中概述的代码路径:

Jsfiddle:

我如何将此条设置为百分比/进度条的动画?它从左下角开始为红色,逆时针旋转。我见过各种各样的例子,但我无法实现它们,因为它们是基于使用pi或直线的径向例子

我基本上希望根据百分比设置绘制路径的动画


在此方面的任何帮助都将不胜感激。

@gamealchest有一个很好的简化想法,即在每一侧使用半圆,而不是Q曲线。这是因为圆的周长很容易计算:2*PI*半径。Q曲线的周长更难计算:在曲线上绘制100多个点,并测量这些点所覆盖的总距离

反过来,您可以轻松地计算路径的总长度。如果要使进度条在从0%到100%的范围内均匀显示,则总长度至关重要

其思想是显示尽可能多的2条线和2个半圆,以表示完成百分比

示例代码和演示:

然后,您可以使用这些计算和完成百分比绘制进度条:

var lineTop=100;
var lineBottom=lineTop+radius*2;
var lineVertMiddle=(lineTop+lineBottom)/2;


function draw(pct){
    var pctLength=totalLength*pct;

    // draw complete path in red
    ctx.clearRect(0,0,canvas.width,canvas.height);
    ctx.strokeStyle='red';
    ctx.beginPath();
    ctx.moveTo(lineLeft,lineBottom);
    ctx.lineTo(lineRight,lineBottom);
    ctx.arc(lineRight,lineVertMiddle,radius,PI/2,-PI/2,true);
    ctx.lineTo(lineLeft,lineTop);
    ctx.arc(lineLeft,lineVertMiddle,radius,PI*3/2,PI/2,true);
    ctx.stroke();

    // draw percent path in green
    ctx.strokeStyle='green';
    ctx.beginPath();
    ctx.moveTo(lineLeft,lineBottom);

    // bottom line counterclockwise
    if(pctLength>0){
        var x=Math.min(pctLength,lineWidth);
        ctx.lineTo(lineLeft+x,lineBottom);
        pctLength-=x;
    }
    // right arc
    if(pctLength>0){
        var sweepAngle=Math.min(PI,PI*pctLength/(circumference/2));
        ctx.arc(lineRight,lineVertMiddle,radius,PI/2,PI/2-sweepAngle,true);
        pctLength-=Math.min(pctLength,circumference/2);
    }
    // top line
    if(pctLength>0){
        var x=Math.min(pctLength,lineWidth);
        ctx.lineTo(lineRight-x,lineTop);
        pctLength-=x;
    }
    // left arc
    if(pctLength>0){
        var sweepAngle=Math.min(PI,PI*pctLength/(circumference/2));
        ctx.arc(lineLeft,lineVertMiddle,radius,PI*3/2,PI*3/2-sweepAngle,true);
    }   

    ctx.stroke();
}

-我看过这个例子,它做了我需要的,但它的形状/样式不正确。人们使用圆是因为参数很容易处理:一个[0;2*PI]中的数字。在您的情况下,您应该做的第一件事是能够绘制[0;100]中任何百分比的条形图。这将涉及计算沿各种曲线的长度。。。不那么容易。。。我在绿色部分的图纸上剪了一个圆圈,做了一个近似值。如果你感兴趣,我可以解释一下。请参见此处:(将debug var设置为true以查看剪辑圆)。@gamealchest这是我最初尝试实现的示例,但我不确定最初在何处绘制圆,因为我知道它更像是一个径向进度条。很好的工作示例。这正是我试图实现@markE的示例。我知道Pi是arc的一个更好的例子,但我不确定最初如何实现。一个特别的例子!
// calculate the total path length
var PI=Math.PI;
var radius=50;
var circumference=2*PI*radius;
var lineLeft=100;
var lineRight=200;
var lineWidth=lineRight-lineLeft;
var totalLength=circumference+lineWidth*2;
var lineTop=100;
var lineBottom=lineTop+radius*2;
var lineVertMiddle=(lineTop+lineBottom)/2;


function draw(pct){
    var pctLength=totalLength*pct;

    // draw complete path in red
    ctx.clearRect(0,0,canvas.width,canvas.height);
    ctx.strokeStyle='red';
    ctx.beginPath();
    ctx.moveTo(lineLeft,lineBottom);
    ctx.lineTo(lineRight,lineBottom);
    ctx.arc(lineRight,lineVertMiddle,radius,PI/2,-PI/2,true);
    ctx.lineTo(lineLeft,lineTop);
    ctx.arc(lineLeft,lineVertMiddle,radius,PI*3/2,PI/2,true);
    ctx.stroke();

    // draw percent path in green
    ctx.strokeStyle='green';
    ctx.beginPath();
    ctx.moveTo(lineLeft,lineBottom);

    // bottom line counterclockwise
    if(pctLength>0){
        var x=Math.min(pctLength,lineWidth);
        ctx.lineTo(lineLeft+x,lineBottom);
        pctLength-=x;
    }
    // right arc
    if(pctLength>0){
        var sweepAngle=Math.min(PI,PI*pctLength/(circumference/2));
        ctx.arc(lineRight,lineVertMiddle,radius,PI/2,PI/2-sweepAngle,true);
        pctLength-=Math.min(pctLength,circumference/2);
    }
    // top line
    if(pctLength>0){
        var x=Math.min(pctLength,lineWidth);
        ctx.lineTo(lineRight-x,lineTop);
        pctLength-=x;
    }
    // left arc
    if(pctLength>0){
        var sweepAngle=Math.min(PI,PI*pctLength/(circumference/2));
        ctx.arc(lineLeft,lineVertMiddle,radius,PI*3/2,PI*3/2-sweepAngle,true);
    }   

    ctx.stroke();
}