javascript - 当在循环期间绘制更多内容时,在 Canvas 中绘制变得越来越慢

标签 javascript html canvas html5-canvas

我正在尝试使用 html5 canvas 从一个点开始逐步绘制 3 条彼此成 120 度的线。每条线的顶点将成为另外 3 个新的中心点,并在每个中心生成另外 3 条线,并重复此操作..

我的问题是,随着绘制的项目越来越多,增量速度变得越来越慢(或者绘图变得更慢)。 (也许我的代码中发生了一些事情,但我不太熟悉 Canvas 到底是如何工作的......)。您可以复制代码并在本地浏览器中运行它来看看我的意思。

请查看我的代码(很容易理解)并告诉我导致此问题的原因。

<!DOCTYPE HTML>
<html>
<head>
<style>
  body {
    margin: 0px;
    padding: 0px;
  }
</style>
</head>
<body>
<canvas id="canvas" ></canvas>

<script>

    window.requestAnimFrame = (function(callback) {
        return window.requestAnimationFrame ||  window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
        function(callback) {
          window.setTimeout(callback, 1000 / 60);
        };
    })();

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    canvas.width= window.innerWidth;
    canvas.height= window.innerHeight;

    // some staring test values
    var centerPt={x:canvas.width/2,y:canvas.height/2};
    var radius=100;
    var angle=0;

    // calculate the 3 endpoints at 120 degree separations
    var endPt000=anglePoint(centerPt,90);
    var endPt120=anglePoint(centerPt,210);
    var endPt240=anglePoint(centerPt,330);

    var length = 0;
    var maxLength = 100;
    var centreSet = new Array();
        centreSet = getCentres();
    var counter = 0;
    var end = centreSet.length;
    init();

    function init() {
        start(centreSet[0].x, centreSet[0].y);
    }

    function start(myX, myY) {
        centerPt.x = myX;
        centerPt.y = myY;
        animate(centerPt, length);
    }

  function animate(centerPt,length) {
    // update
    // clear
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // draw stuff
    draw(centerPt,length);
    length = length + 1;
    // request new frame
    if(length < maxLength){
        requestAnimFrame(function() {
          animate(centerPt,length);
        });
    }
    else{
        if(counter < end){
            counter = counter + 1;
            centerPt.x = centreSet[counter].x;
            centerPt.y = centreSet[counter].y;
            endPt000=anglePoint(centerPt,90);
            endPt120=anglePoint(centerPt,210);
            endPt240=anglePoint(centerPt,330);
            length = 0;
            setTimeout(function(){animate(centerPt, length);},600);
        }
    }
  }

// draw a red center dot
// draw 3 blue endpoint dots
// draw 3 lines from center going slider% of the way to the endpoints 
function draw(centerPt,sliderValue){

    var pct=sliderValue;
    ctx.clearRect(0,0,canvas.width,canvas.height);
    line(centerPt,pointAtPercent(centerPt,endPt000,pct),"green");
    line(centerPt,pointAtPercent(centerPt,endPt120,pct),"green");
    line(centerPt,pointAtPercent(centerPt,endPt240,pct),"green");

}

// calc XY at the specified angle off the centerpoint 
function anglePoint(centerPt,degrees){
    var x=centerPt.x-radius*Math.cos( degrees*Math.PI/180 );
    var y=centerPt.y-radius*Math.sin( degrees*Math.PI/180 );
    return({x:x,y:y});
}

// just draw a line from point1 to point2
function line(pt1,pt2,color){
   // ctx.beginPath();
    ctx.moveTo(pt1.x,pt1.y);
    ctx.lineTo(pt2.x,pt2.y);
    ctx.strokeStyle=color;
    ctx.lineWidth=2;
    ctx.stroke();
}

// calc XY which is a specified percent distance from pt1 to pt2
function pointAtPercent(pt1,pt2,sliderValue) {
    // calculate XY at slider% towards pt2
    var x = pt1.x + (pt2.x-pt1.x) * sliderValue/100;
    var y = pt1.y + (pt2.y-pt1.y) * sliderValue/100;
    return({x:x,y:y});
}

//the following are used to get all the center points...
function getCentres() {
    var x = window.innerWidth/2;
    var y = window.innerHeight/2;
    centreSet[0] = centerPt;
    var ref = 0;
    var end = 0;
    var b = true;
    var tempCenter = centerPt;
    for(var j = 0; j < 5; j++){
        tempCenter = centreSet[ref];
        end = end + 1;
        centreSet[end] = anglePoint(tempCenter,90);
        end = end + 1;
        centreSet[end] = anglePoint(tempCenter,210);
        end = end + 1;
        centreSet[end] = anglePoint(tempCenter,330);

        ref = ref+1;

    }
    return centreSet;
}
   </script>
   </body>
</html>

最佳答案

问题是您正在追加和追加路径。这意味着每次调用 lines() 时,新行和所有旧行都会被描边。您不会清楚地看到这一点,因为旧线是在顶部相同位置绘制的。随着添加的线条越来越多,抚摸它们所需的时间也越来越多..

为了防止这种情况发生,你需要中断路径。使用 beginPath() 执行此操作。

如果您激活注释掉的行,它应该可以正常工作:

function line(pt1,pt2,color){
    ctx.beginPath(); //<-- activate this
    ctx.moveTo(pt1.x,pt1.y);
    ctx.lineTo(pt2.x,pt2.y);
    ctx.strokeStyle=color;
    ctx.lineWidth=2;
    ctx.stroke();
}

关于javascript - 当在循环期间绘制更多内容时,在 Canvas 中绘制变得越来越慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16932640/

相关文章:

javascript - 如何让一个 div 随着窗口大小的调整而移动,而不会将其他 div 推开?

javascript - 将对象保存在模块中并从不同的模块访问它

javascript - 从 js 读取/写入 json 到服务器上的文件(不是服务器应用程序)

java - struts在没有js的情况下验证后专注于字段

javascript - 添加CSS后背景颜色没有改变

javascript - IE Canvas dataURI 安全错误

jquery - Canvas 外导航菜单无法正常工作

javascript - Canvas .toDataURL() 返回部分损坏的图像

javascript - 任何人都可以建议从 web 的 javascript 触摸事件开始的地方吗?

javascript - 单击时将类添加到侧边栏父菜单和子菜单