[英]How to animate tree in HTML5 canvas
我在畫布上畫了這棵樹,現在我想為它設置動畫,讓它看起來像是在生長。 我是動畫初學者,所以我很樂意提供任何輸入和想法! 此外,這棵樹應該每次都以不同的方式生長,如果可能的話,看起來也不一樣。 謝謝!
<!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>
您可以通過將樹線定義和繪圖分成 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>
這背后有一整套科學,恐怕沒有人會給你一個簡單、干凈的解決方案。 當然,我敢讓任何人證明我是錯的,我想親眼看看。 :)
但是嘗試閱讀有關 L-Systems 和在網上生長的分形樹的內容。 這是一個很好的例子,你可以查看源代碼並檢查那里的“grow.js”腳本:
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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.