Metatunnel in javascript を試してみた
連日の HTML5::Canvas ネタ投下です。Canvasのテストデータに飢えてて、色々と試したりしてます。
Ajaxian で紹介されていた
http://ajaxian.com/archives/metatunnel-1k-demo-js-vs-os
を、所々最適化して、IEでも動くようにしてみたのがこちら、
http://pigs.sourceforge.jp/blog/20090428/Metatunnel.htm
元の js のほぼ1.5倍速で動作するようです。
IE でも一応動きますが、うちの IE6 だと2秒に1フレームしか描画されませんでした。
IEで動かす場合は、先に Silverlight をインストールすることをお勧めします。
Google Chrome だとかなりなめらかに動きます。Opera10α や Firefox3.1β3 もそれなりですね。
ソース
<script type="text/xaml" id="xaml"><?xml version="1.0"?> <Canvas xmlns="http://schemas.microsoft.com/client/2007"></Canvas></script> <script type="text/javascript" src="uupaa-excanvas.js"></script> <script type="text/javascript"> var time=0; var sin=Math.sin;var cos=Math.cos;var sqrt=Math.sqrt; var hex = (function() { var rv = [], i, j; for (i = 0; i < 16; ++i) { for (j = 0; j < 16; ++j) { rv[i * 16 + j] = i.toString(16) + j.toString(16); } } return rv; })(); function obj(x,y,z,t){ var f=1.0,_x,_y,_z; _x = cos(t)+sin(t*0.2)-x, _y = 0.3-y, _z = 2.0+cos(t*0.5)*0.5-z; f*=sqrt(_x*_x+_y*_y+_z*_z) _x = -cos(t*0.7)-x, _y = 0.3-y, _z = 2.0+sin(t*0.5)-z; f*=sqrt(_x*_x+_y*_y+_z*_z) _x = -sin(t*0.2)*0.5-x, _y = sin(t)-y, _z = 2.0-z; f*=sqrt(_x*_x+_y*_y+_z*_z) f*=cos(y)*cos(x)-0.1-cos(z*7.0+t*7.0)*cos(x*3.0)*cos(y*4.0)*0.1; return f; } function evalColor(x,y,t){ var vx=x*2.0-1.0; var vy=-y*2.0+1.0; var s=0.4; var ox=vx;var oy=vy*1.25;var oz=0.0; var dx=(vx+cos(t)*0.3)/64.0;var dy=vy/64.0;var dz=1.0/64.0; var tt=0.0; var g=1.0; var _f, _x, _y, _z; var _dx, _dy, _dz; while((g>s)&&(tt<375)){ _f = 1.0; _x = ox+dx*tt; _y = oy+dy*tt; _z = oz+dz*tt; _dx = cos(t)+sin(t*0.2)-_x, _dy = 0.3-_y, _dz = 2.0+cos(t*0.5)*0.5 - _z; _f*=sqrt(_dx*_dx+_dy*_dy+_dz*_dz); _dx = -cos(t*0.7)-_x, _dy = 0.3-_y, _dz = 2.0+sin(t*0.5) - _z; _f*=sqrt(_dx*_dx+_dy*_dy+_dz*_dz); _dx = -sin(t*0.2)*0.5-_x, _dy = sin(t)-_y, _dz = 2.0 - _z; _f*=sqrt(_dx*_dx+_dy*_dy+_dz*_dz); _f*=cos(_y)*cos(_x)-0.1-cos(_z*7.0+t*7.0)*cos(_x*3.0)*cos(_y*4.0)*0.1; g = _f; tt+=g*4; }; var color=0.0; var dxtt=ox+dx*tt;var dytt=oy+dy*tt;var dztt=oz+dz*tt; var objd=obj(dxtt,dytt,dztt,t); var nx=objd-obj(dxtt+0.01,dytt,dztt,t); var ny=objd-obj(dxtt,dytt+0.01,dztt,t); var nz=objd-obj(dxtt,dytt,dztt+0.01,t); var d=sqrt(nx*nx+ny*ny+nz*nz);ny=ny/d;nz=nz/d; var max1 = -0.5*nz, max2 = -0.5*ny+0.5*nz; color+=(max1>0?max1:0)+(max2>0?max2:0)*0.5; var r=(color+0.1*tt*0.025); var g=(color+0.2*tt*0.025); var b=(color+0.5*tt*0.025); if (r<0) r=0; else if (r>1) r=1; if (g<0) g=0; else if (g>1) g=1; if (b<0) b=0; else if (b>1) b=1; // return ((r*255)&255)+","+((g*255)&255)+","+((b*255)&255); return "#"+hex[(r*255)&0xff]+hex[(g*255)&0xff]+hex[(b*255)&0xff]; } var canvas; var ctx; function draw(){ ctx.clearRect(0, 0, canvas.width, canvas.height); var px, py, maxr=64; for(x=0;x<maxr;++x){ px=x/maxr; for(y=0;y<maxr;++y){ py=y/maxr; // ctx.fillStyle="rgb("+eval(px,py,time)+")"; ctx.fillStyle=evalColor(px,py,time); ctx.fillRect(x*2,y*2,2,2); } } time+=0.1; setTimeout(draw,1); }; window.onload = function() { uuCanvas.ready(function() { canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); draw(); }); } </script> <canvas id="canvas" width="128" height="128"></canvas>