2013-06-05 22 views
0

我正在嘗試逐漸使用html5畫布繪製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> 

回答

2

問題是你正在追加和追加路徑。這意味着每次您撥打stroke()時,新線路會與所有舊線路一起觸發。由於舊線條在同一位置的頂部繪製,因此您不會看清楚這一點。隨着越來越多的線添加更多的時間來撫摸他們..

爲了防止這種情況,你需要打破路徑。用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(); 
} 
+0

但通過添加調用beginPath(),這意味着烏拉圭回合開始一個新的路徑,所以每次當u請求一個新的框架,內容你以前畫畫都走了... –

+0

嗨,肯也許你可以回答我的問題。我刪除beginPath()的唯一原因是因爲我想保留已經在畫布中繪製的內容。我嘗試了context.save()和restore(),但它們都不起作用,因爲save()只會保存trokeStyle,fillStyle,globalAlpha,lineWidth,lineCap ...但不是路徑! (參考:http://html5.litten.com/understanding-save-and-restore-for-the-canvas-context/) –

+2

如果你想保留你已經畫出的東西,只需用'ctx註釋掉這行。在你的'draw()'函數中使用clearRect'。 – K3N