簡體   English   中英

如何在 HTML5 畫布中為樹設置動畫

[英]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 個單獨的步驟來為您生長的樹制作動畫。 這樣你就可以為你的樹線繪制動畫。

  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>

這背后有一整套科學,恐怕沒有人會給你一個簡單、干凈的解決方案。 當然,我敢讓任何人證明我是錯的,我想親眼看看。 :)

但是嘗試閱讀有關 L-Systems 和在網上生長的分形樹的內容。 這是一個很好的例子,你可以查看源代碼並檢查那里的“grow.js”腳本:

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

 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM