当我看到这件作品的时候,我表示非常喜欢。这个作品的产生不仅仅需要编程和算法,作者肯定是个充满了艺术细胞的人。倘若有什么canvas艺术作品比赛的话,我想它就是获奖的那个。
先观赏下演示吧。注意,要看到效果,请确保你的浏览器支持 HTML 5。如果你还在使用旧版 IE,请更换新版浏览器。
代码如下:
001 |
function fillCircle(ctx, r) |
002 |
{ |
003 |
ctx.beginPath(); |
004 |
ctx.moveTo(r, 0); |
005 |
ctx.fillStyle = 'rgb(245,50,50)'; |
006 |
ctx.arc(0,0,r,0,Math.PI*2,true); |
007 |
ctx.fill(); |
008 |
} |
009 |
010 |
function branch(ctx, r, d, t, a) |
011 |
{ |
012 |
ctx.save(); |
013 |
ctx.rotate(t*a); |
014 |
ctx.translate(0, -r*(1+d)); |
015 |
wing(ctx, r*d, a); |
016 |
ctx.restore(); |
017 |
} |
018 |
019 |
function feather(ctx, r) |
020 |
{ |
021 |
if ( r < 3 ) return; |
022 |
var d = 0.85; |
023 |
ctx.rotate(-0.03*Math.PI); |
024 |
ctx.translate(0, -r*(1+d)); |
025 |
fillCircle(ctx, r); |
026 |
feather(ctx, r*d); |
027 |
} |
028 |
029 |
function wing(ctx, r, a) |
030 |
{ |
031 |
if ( r < 2.9 ) return; |
032 |
fillCircle(ctx, r); |
033 |
branch(ctx, r, 0.9561, 0.03*Math.PI, a); |
034 |
ctx.save(); |
035 |
ctx.rotate(0.55*Math.PI); |
036 |
feather(ctx, 0.8*r); |
037 |
ctx.restore(); |
038 |
} |
039 |
040 |
function tail(ctx, s, a) |
041 |
{ |
042 |
if ( s < 0.5 ) return; |
043 |
var d = 0.98; // decay |
044 |
fillCircle(ctx, s); |
045 |
ctx.rotate(-0.15*a); |
046 |
ctx.translate(0, s*(1+d)); |
047 |
tail(ctx, s*d, a); |
048 |
} |
049 |
050 |
function head(ctx) |
051 |
{ |
052 |
fillCircle(ctx, 22); |
053 |
054 |
// mouth |
055 |
ctx.save(); |
056 |
ctx.translate(-15, -3); |
057 |
ctx.beginPath(); |
058 |
ctx.fillStyle = "white"; |
059 |
ctx.arc(0,0,10,0,Math.PI*2,true); |
060 |
ctx.fill(); |
061 |
ctx.restore(); |
062 |
063 |
// eye |
064 |
ctx.translate(9, -4); |
065 |
ctx.beginPath(); |
066 |
ctx.fillStyle = "black"; |
067 |
ctx.arc(0,0,5,0,Math.PI*2,true); |
068 |
ctx.fill(); |
069 |
070 |
// horn |
071 |
ctx.translate(6, -8); |
072 |
ctx.rotate(0.6*Math.PI); |
073 |
wing(ctx, 5.5, 1.8); |
074 |
} |
075 |
076 |
function neck(ctx, s) |
077 |
{ |
078 |
if ( s < 10 ) { head(ctx); return; } |
079 |
|
080 |
var d = 0.85; |
081 |
fillCircle(ctx, s); |
082 |
083 |
ctx.save(); |
084 |
ctx.rotate(-Math.PI/2); |
085 |
ctx.translate(0, s); |
086 |
fillCircle(ctx, s/2); |
087 |
ctx.restore(); |
088 |
089 |
ctx.rotate(-0.15); |
090 |
ctx.translate(0, -s*(1+d)); |
091 |
neck(ctx, s*d); |
092 |
} |
093 |
094 |
function loop(ctx, i) { |
095 |
var inner = function() { |
096 |
i++; |
097 |
098 |
ctx.fillStyle = "white"; |
099 |
ctx.fillRect(-1500,-1500,3000,3000); |
100 |
101 |
ctx.save(); |
102 |
ctx.translate(0, Math.cos(i*0.1)*40); |
103 |
104 |
var a = Math.sin(i*0.1); |
105 |
106 |
// right wing |
107 |
ctx.save(); |
108 |
ctx.rotate(Math.PI*0.4); |
109 |
wing(ctx, 18, a); |
110 |
ctx.restore(); |
111 |
112 |
// left wing |
113 |
ctx.save(); |
114 |
ctx.scale(-1, 1); |
115 |
ctx.rotate(Math.PI*0.4); |
116 |
wing(ctx, 18, a); |
117 |
ctx.restore(); |
118 |
119 |
// tail |
120 |
ctx.save(); |
121 |
tail(ctx, 20, Math.sin(i*0.05)); |
122 |
ctx.restore(); |
123 |
124 |
// head |
125 |
neck(ctx, 22); |
126 |
|
127 |
ctx.restore(); |
128 |
setTimeout(inner, 35); // change speed here |
129 |
}; |
130 |
131 |
return inner; |
132 |
} |
133 |
134 |
function draw() { |
135 |
var canvas = document.getElementById("canvas"); |
136 |
var ctx = canvas.getContext("2d"); |
137 |
138 |
ctx.translate(490, 410); |
139 |
ctx.scale(0.4,0.4); |
140 |
setTimeout(loop(ctx, 1), 1); |
141 |
} |
HTML
1 |
< body onload = "draw()" > |
2 |
< canvas id = "canvas" width = "1000" height = "1000" ></ canvas > |
3 |
</ body > |