2013-06-02 114 views
2

我想在HTML5和Javascript中畫出一些不斷增長的線條。這是我想要做的:HTML5畫布不斷撫摸着線條

位於我屏幕中心的點將有3條線彼此成長(相互之間120度)到一定的長度,比如50像素,然後這3個頂點中的每一個都會變成一個新的中心和另外3條線。

(我不能發表圖片由於低信譽我有,希望你明白我的意思生根粉的形象在這裏...)

我已經編寫的功能有我需要的所有點的陣列中心,從我的屏幕中心開始。我想在這個數組上畫一個循環來畫線。我不想直接使用筆畫,以便線條出現在屏幕上。我想要有點像線條一點一點地畫出來(英語不好,請原諒我的英語),直到它達到預定義的長度。然而我的代碼在這裏工作得不是很好,它只顯示所有的中心點,只有最後一箇中心點有運動,有3條線增長...

我需要知道正確的方法來做到這一點。 .. 提前謝謝了!

(請忽略我的代碼中的可變時間或開始時間......)

<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('myCanvas'); 
canvas.width= window.innerWidth; 
canvas.height= window.innerHeight; 
var context = canvas.getContext('2d'); 
var totalLength = 50; 

var centreSet = new Array(); 
var counter = 0; 

var centre = { 
    x: canvas.width/2, 
    y: canvas.height/2, 
}; 

var myLine = { 
    length : 0, 
    color : 'grey', 
    lineWidth : 0.5, 
}; 

function drawLine(centre, context, mylength) { 
    context.beginPath(); 
    context.moveTo(centre.x, centre.y); 
    context.lineTo(centre.x, centre.y - mylength); 
    context.moveTo(centre.x, centre.y); 
    context.lineTo(centre.x - 0.866 * mylength, centre.y + mylength/2); 
    context.moveTo(centre.x, centre.y); 
    context.lineTo(centre.x + 0.866 * mylength, centre.y + mylength/2); 
    context.lineWidth = myLine.lineWidth; 
    context.strokeStyle = myLine.color; 
    context.closePath(); 
    context.stroke(); 
} 

function startAnimate(centre, canvas, context, startTime, mylength) { 
     // update 
    var time = (new Date()).getTime() - startTime; 
    var linearSpeed = 5; 
    // pixels/second 
    var newX = linearSpeed/10; 

    if(mylength < totalLength) { 
     mylength = mylength + newX; 
     // clear 
     //context.clearRect(0, 0, canvas.width, canvas.height); 
     drawLine(centre, context, mylength); 

     // request new frame 
     requestAnimFrame(function() { 
      startAnimate(centre, canvas, context, startTime, mylength); 
     }); 
    } 

} 

function animate(centre, canvas, context, startTime){ 
      //create array to have all the center points 
    centreSet = getCentres(); 
    for (var i = 0; i < centreSet.length; i++){ 
        //pass the x and y values in a object for each center we have in the array 
     centre.x = str2x(centreSet[i]); 
     centre.y = str2y(centreSet[i]); 
     startAnimate(centre, canvas, context, startTime, 0); 
    } 
} 

    setTimeout(function() { 
    var startTime = (new Date()).getTime(); 
    animate(centre, canvas, context, startTime); 
}, 1000); 

我剛編輯你的代碼,我增加了以下部分:

var length = 0; 
for(var i = 0; i < 380; i++){ 
window.setTimeout(function() {drawFrame(length);},16.67); 
length = length + 0.25; 
} 

我期待屏幕似乎會逐漸繪製增量線,直到達到我想要的長度。但是,看起來整個增量過程沒有顯示,只顯示完成的繪圖。

有誰能告訴我爲什麼?

回答

1

至於爲什麼你的動畫L您的後續問題OOP失敗

通過將setTimeout放在for循環中,每個新的setTimeout都取消之前的setTimeout。

所以你只剩下最後一次setTimeout運行完成。

在動畫循環,你通常每一個「框」中做3兩件事:

  1. 更改一些數據,以反映新的框架是如何從上一幀不同。
  2. 繪製框架。
  3. 測試動畫是否完整。如果不是,請執行另一個幀(轉到#1)。

setTimeout功能是用來做的#3的最後部分(另做幀)

所以的setTimeout真的充當循環播放動畫。 ---你的for循環是不需要的。

這是你將如何調整你的代碼,以遵循這個模式:

var length=0; 
var maxLength=50; 

function draw(){ 

    // make the line .25 longer 
    length=length+.25; 

    // draw 
    drawFrame(length); 

    // test if the line is fully extended 
    // if not, call setTimeout again 
    // setTimeout(draw,100) will call this same draw() function in 100ms 
    if(length<maxLength){ 
     setTimeout(draw,100); 
    } 
} 
+0

謝謝。我已經想通了這一切! –

1

[編輯:包括子對象的產卵線到達終端的距離之後]

在你的代碼並沒有產生新的中心點當線路達到其最大擴展。

我建議每個中心的對象至少有爲了產生一個新的集合中心的對象時,他們的線路到達終端長度這麼多的信息:

var newCentrePoint={ 
    x:x, 
    y:y, 
    maxLength:newMaxLength, 
    growLength:growLength, 
    currentLength:0, 
    isActive:true 
} 

的x,y是中心點的座標。

maxLength是3行在終止前的最大擴展。

growLength是每條線在每個新幀中的增長量。

currentLength是行的當前長度。

isActive是指示如果這一點是生長線(真)的標誌,或者如果它是封端的(假)

然後,當每個線到達終端長度可以產卵像這樣的新的一組行:

// spawns 3 new centre points – default values are for testing 
function spawn(point,newMaxLength,newColor,growLength,newLineWidth){ 
    var max=newMaxLength||point.maxLength/2; 
    var color=newColor|| (colors[++colorIndex%(colors.length)]); 
    var grow=growLength||point.growLength/2; 
    var lw=newLineWidth||point.lineWidth-1; 

    // new center points are spawned at the termination points of the 3 current lines 
    newPoint((point.x),(point.y-point.maxLength),max,color,grow,lw); 
    newPoint((point.x-0.866*point.maxLength),(point.y+point.maxLength/2),max,color,grow,lw); 
    newPoint((point.x+0.866*point.maxLength),(point.y+point.maxLength/2),max,color,grow,lw); 
} 

// creates a new point object and puts in the centreSet array for processing 
function newPoint(x,y,newMaxLength,newColor,growLength,newLineWidth){ 
    var newPt={ 
     x:x, 
     y:y, 
     maxLength:newMaxLength, 
     color:newColor, 
     lineWidth:newLineWidth, 
     growLength:growLength, 
     currentLength:0, 
     isActive:true 
    } 
    centreSet.push(newPt); 
} 

這裏是代碼和一個小提琴:http://jsfiddle.net/m1erickson/Vc8Gf/

<!doctype html> 
<html> 
<head> 
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> 
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> 

<style> 
    body{ background-color: ivory; } 
    canvas{border:1px solid red;} 
</style> 

<script> 
$(function(){ 

    var canvas=document.getElementById("canvas"); 
    var context = canvas.getContext('2d'); 

    // colors 
    var colors=["red","blue","gold","purple","green"]; 
    var colorIndex=0; 

    // 
    var centreSet=[] 
    var generations=1; 

    // seed point 
    newPoint(canvas.width/2,canvas.height/2,100,"red",15); 

    // start 
    draw(); 

    // 
    function draw(){ 
     // 
     context.clearRect(0,0,canvas.width,canvas.height); 
     // 
     for(var i=0;i<centreSet.length;i++){ 
      // 
      var centre=centreSet[i]; 


      // 
      if(centre.isActive){ 
       // 
       centre.currentLength+=centre.growLength; 
       // 
       if(centre.currentLength>=centre.maxLength){ 
        centre.isActive=false; 
        centre.currentLength=centre.maxLength; 
        spawn(centre); 
       } 
      } 
      // 
      drawLines(centre); 
     } 
     // 
     if(generations<120){ 
      setTimeout(draw,500); 
     }else{ 
      context.font="18pt Verdana"; 
      context.fillText("Finished 120 generations",40,350); 
     } 
    } 


    function spawn(point,newMaxLength,newColor,growLength,newLineWidth){ 
     var max=newMaxLength||point.maxLength/2; 
     var color=newColor|| (colors[++colorIndex%(colors.length)]); 
     var grow=growLength||point.growLength/2; 
     var lw=newLineWidth||point.lineWidth-1; 
     newPoint((point.x),(point.y-point.maxLength),max,color,grow,lw); 
     newPoint((point.x-0.866*point.maxLength),(point.y+point.maxLength/2),max,color,grow,lw); 
     newPoint((point.x+0.866*point.maxLength),(point.y+point.maxLength/2),max,color,grow,lw); 
     generations++; 
    } 

    function newPoint(x,y,newMaxLength,newColor,growLength,newLineWidth){ 
     var newPt={ 
      x:x, 
      y:y, 
      maxLength:newMaxLength, 
      color:newColor, 
      lineWidth:newLineWidth, 
      growLength:growLength, 
      currentLength:0, 
      isActive:true 
     } 
     centreSet.push(newPt); 
    } 


    function drawLines(centre) { 

     var length=centre.currentLength; 
     // 
     context.beginPath(); 
     context.moveTo(centre.x, centre.y); 
     context.lineTo(centre.x, centre.y - length); 
     // 
     context.moveTo(centre.x, centre.y); 
     context.lineTo(centre.x - 0.866 * length, centre.y + length/2); 
     // 
     context.moveTo(centre.x, centre.y); 
     context.lineTo(centre.x + 0.866 * length, centre.y + length/2); 
     // 
     context.strokeStyle=centre.color; 
     context.lineWidth = centre.lineWidth; 
     context.stroke(); 
    } 

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

</head> 

<body> 
    <canvas id="canvas" width=400 height=400></canvas> 
</body> 
</html> 
+0

嗨,馬克,我想知道我做錯了,我的代碼,因爲輸出結果顯示所有的中心點和增量繪製的最後一點.. –

+0

問候!在您的代碼中,您的中心對象可以擴展爲包含足夠的數據,以在線到達終點距離後產生3個子中心對象。我添加到我的答案來說明如何。 – markE

+0

在我的代碼中,我已經有一個數組,其中包含所有需要產生3行的中心點,它位於aminate(),centreSet = getCentres(); –