2014-12-03 118 views
1

我在畫布上畫了這棵樹,現在我想爲它製作動畫並使它看起來像是在增長。我是一個有動畫的初學者,所以我會很高興爲任何輸入和想法!此外,樹應該每次都有不同的增長,如果可能的話,樹看起來不一樣。 謝謝!如何在HTML5畫布中動畫樹

<!DOCTYPE html> 
<html lang="en"> 
    <head> 
     <title>tree</title> 
    </head> 

    <body onload="init();"> 

     <canvas id="canvas" width="1200" height="600" ></canvas> 

     <script type="text/javascript" > 

      init = function() { 

       var x1 = 400; 
       var y1 = 300; 

       var x2 = 400; 
       var y2 = 200; 

       var angle = 0.1 * Math.PI; 
       var depth = 6; 

       drawTree(x1, y1, x2, y2, angle, depth); 
      } 

      drawTree = function(x1, y1, x2, y2, angle, depth){ 
       var context = document.getElementById('canvas').getContext('2d'); 

       context.strokeStyle = 'rgb(0, 0, 0)'; 
       context.lineWidth = depth; 
       context.beginPath(); 
       context.moveTo(x1, y1); 
       context.lineTo(x2, y2); 
       context.stroke(); 

       if(depth > 0){ 
        var x = x2 - x1; 
        var y = y2 - y1; 

        var scale = 0.5 + Math.random() * 0.5; 

        x *= scale; 
        y *= scale; 

        var xLeft = x * Math.cos(-angle) - y * Math.sin(-angle); 
        var yLeft = x * Math.sin(-angle) + y * Math.cos(-angle); 

        var xRight = x * Math.cos(+angle) - y * Math.sin(+angle); 
        var yRight = x * Math.sin(+angle) + y * Math.cos(+angle); 

        xLeft += x2; 
        yLeft += y2; 

        xRight += x2; 
        yRight += y2; 

        drawTree(x2, y2, xLeft, yLeft, angle, depth - 1); 
        drawTree(x2, y2, xRight, yRight, angle, depth - 1); 
       } 
      } 

     </script> 
    </body> 
</html> 
+0

http://d3js.org/ – mccainz 2014-12-03 17:49:34

+0

一個超級幼稚的方法是把你的畫叫成[' setTimeout()'](http://jsfiddle.net/brbcoding/tkuwc5zg/)(但是這在慢速下看起來很糟糕)。你可能想要抓住每個'分支'的開始和結束點,並在開始點和結束點內的中間點重繪畫布(使用'requestAnimationFrame'或類似方法在一些繪製循環內部)。 – brbcoding 2014-12-03 17:50:41

+0

這就是我的意思 - http://jsfiddle.net/brbcoding/2ym5710m/ – brbcoding 2014-12-03 18:05:49

回答

1

這裏有一個完整的科學,恐怕沒有人會給你一個簡單,乾淨的解決方案。當然,我敢讓任何人證明我錯了,我想親自看看。 :)

但嘗試讀一些關於L系統和網上生長的分形樹。這裏有一個很好的例子,你可以看看源代碼,並視察那裏的「grow.js」腳本:

https://developer.cdn.mozilla.net/media/uploads/demos/c/o/codepo8/1a61b64545e9e7b1113eef901831ec61/fractal-trees_1313841385_demo_package/index.html

3

您可以通過分離您的樹行定義和您的圖紙變成2動畫的成長樹單獨的步驟。這樣你可以爲你的樹形圖繪製動畫。

  1. 定義組成樹的所有行。

  2. 使用動畫循環繪製以主分支開始並以最小樹枝結束的行。

這裏的註釋代碼和演示:

var canvas=document.getElementById("canvas"); 
 
var context=canvas.getContext("2d"); 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 

 

 
// tree definitions 
 
var x1 = 200; 
 
var y1 = 500; 
 
var x2 = 200; 
 
var y2 = 400; 
 

 
// growing definitions 
 
var angle = 0.1 * Math.PI; 
 
var depth = 6; 
 

 
// save segments for later animation 
 
var branches=[]; 
 
for(var i=0;i<=depth;i++){branches.push([]);} 
 
var segments=[]; 
 
var segmentIndex=0; 
 

 
// animation variables 
 
var nextTime=0; 
 
var delay=16*5; 
 

 
///////////// Do stuff! 
 

 
// define the tree 
 
defineTree(x1, y1, x2, y2, angle, depth); 
 

 
// create a combined array of segments to be drawn with animation 
 
for(var i=branches.length-1;i>=0;i--){ 
 
    segments=segments.concat(branches[i]); 
 
} 
 

 
// load leaf images and then start animating 
 
var leaves=new Image(); 
 
leaves.onload=function(){ 
 
    // animate drawing the tree 
 
    requestAnimationFrame(animate); 
 
} 
 
leaves.src='https://dl.dropboxusercontent.com/u/139992952/multple/leaves.png'; 
 

 

 

 
///////////// functions 
 

 
// function to reiteratively define all segments of a tree 
 
function defineTree(x1, y1, x2, y2, angle, depth){ 
 

 
    var segment={ 
 
    x1:x1,y1:y1, 
 
    x2:x2,y2:y2, 
 
    linewidth:depth, 
 
    }; 
 
    branches[depth].push(segment); 
 

 
    if(depth > 0){ 
 
    var x = x2 - x1; 
 
    var y = y2 - y1; 
 

 
    var scale = 0.5 + Math.random() * 0.5; 
 

 
    x *= scale; 
 
    y *= scale; 
 

 
    var xLeft = x * Math.cos(-angle) - y * Math.sin(-angle); 
 
    var yLeft = x * Math.sin(-angle) + y * Math.cos(-angle); 
 

 
    var xRight = x * Math.cos(+angle) - y * Math.sin(+angle); 
 
    var yRight = x * Math.sin(+angle) + y * Math.cos(+angle); 
 

 
    xLeft += x2; 
 
    yLeft += y2; 
 

 
    xRight += x2; 
 
    yRight += y2; 
 

 
    defineTree(x2, y2, xLeft, yLeft, angle, depth - 1); 
 
    defineTree(x2, y2, xRight, yRight, angle, depth - 1); 
 
    } 
 
} 
 

 
// draw 1 segment of the tree 
 
function drawSegment(segment){ 
 
    context.strokeStyle = 'rgb(0, 0, 0)'; 
 
    context.lineWidth = segment.linewidth; 
 
    context.beginPath(); 
 
    context.moveTo(segment.x1, segment.y1); 
 
    context.lineTo(segment.x2, segment.y2); 
 
    context.stroke(); 
 
    // 
 
    if(segment.linewidth==0){ 
 
    var dx=segment.x2-segment.x1; 
 
    var dy=segment.y2-segment.y1; 
 
    var angle=Math.atan2(dy,dx)+Math.PI/2; 
 
    var i=parseInt(Math.random()*2.99); 
 
    var j=parseInt(Math.random()*1.99); 
 
    context.save(); 
 
    context.translate(segment.x2,segment.y2); 
 
    context.rotate(angle); 
 
    context.scale(.25,.25); 
 
    context.drawImage(leaves,127*i,142*j,127,142,-127/2,-142/2,127,142); 
 
    context.restore(); 
 
    } 
 
} 
 

 

 
// animate drawing each segment of the tree 
 
function animate(currentTime){ 
 

 
    // request another loop until all segments have been drawn 
 
    if(segmentIndex<segments.length){ 
 
    requestAnimationFrame(animate); 
 
    } 
 

 
    // delay until nextTime 
 
    if(currentTime<nextTime){return;} 
 

 
    // set the new nextTime 
 
    nextTime=currentTime+delay; 
 

 
    // draw the current segment 
 
    drawSegment(segments[segmentIndex]); 
 

 
    // increment the segmentIndex for next loop 
 
    segmentIndex++; 
 
}
body{ background-color: ivory; padding:10px; } 
 
#canvas{border:1px solid red;}
<canvas id="canvas" width=400 height=500></canvas>