问题
I drew this tree in canvas and now i want to animate it and make it look like it is growing. I am a beginner with animations so i would be happy for any input and ideas! Also the tree is supposed to grow differently every time and not look the same if that is possible. Thanks!
<!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>
回答1:
You can animate your growing tree by separating your tree-line definitions and your drawings into 2 separate steps. That way you can animate the drawing of your tree-lines.
Define all the lines that make up your tree.
Use an animation loop to draw those lines starting with the main branch and ending with the smallest twigs.
Here's annotated code and a Demo:
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>
回答2:
There's a whole science behind this, I am afraid noone will give you a simple, clean solution. Of course, I dare anyone to prove me wrong, I would like to see that myself. :)
But try to read something about L-Systems and fractal tree growing on the net. Here's a nice example, you can look into the source code and inspect the "grow.js" script there:
https://developer.cdn.mozilla.net/media/uploads/demos/c/o/codepo8/1a61b64545e9e7b1113eef901831ec61/fractal-trees_1313841385_demo_package/index.html
来源:https://stackoverflow.com/questions/27278116/how-to-animate-tree-in-html5-canvas