Skip to content

Instantly share code, notes, and snippets.

@mindware
Created March 7, 2015 07:36
Show Gist options
  • Save mindware/e7e02d8f2d0ab863abd5 to your computer and use it in GitHub Desktop.
Save mindware/e7e02d8f2d0ab863abd5 to your computer and use it in GitHub Desktop.
How to distort an image to create flag waving in the wind effect using html5 canvas
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<title>HTML Canvas Flag Wave</title>
<style type="text/css" media="screen">
body { background:#eee }
#flag { position:absolute; top:50%; left:50% }
</style>
<script type="text/javascript">
window.onload = function(){
var flag = document.getElementById('flag');
drawAmericanFlag( flag, 320 );
flag.style.marginLeft = -(flag.width/2)+'px';
flag.style.marginTop = -(flag.height/2)+'px';
var timer = waveFlag( flag, 30, 15, 200, 200 );
};
function drawAmericanFlag( canvas, width ){
// http://www.montney.com/flag/proportions.htm
var a = width / 1.9;
var b = width;
var c = 7*a/13;
var d = 0.76*a;
var e = 0.054*a;
var g = 0.063*a;
var k = 0.0616*a;
var l = a / 13;
canvas.width = b;
canvas.height = a;
var ctx = canvas.getContext('2d');
// Stripes
ctx.fillStyle = '#fff';
ctx.fillRect(0,0,b,a);
ctx.fillStyle = '#900';
for (var i=0;i<13;i+=2) ctx.fillRect(0,i*l,b,l);
// Field
ctx.fillStyle = '#009';
ctx.fillRect(0,0,d,c);
// Stars
ctx.fillStyle = '#fff';
for (var row=1;row<=9;++row){
for (var col=1;col<=11;++col){
if ((row%2==1 && col%2==0) || (row%2==0 && col%2==1)) continue;
ctx.beginPath();
ctx.arc(col*g,row*e,k/3,0,Math.PI*2);
ctx.closePath();
ctx.fill();
}
}
// Border
ctx.strokeStyle = 'rgba(0,0,0,0.8)';
ctx.lineWidth = 1;
ctx.strokeRect( 0, 0, b, a );
}
function waveFlag( canvas, wavelength, amplitude, period, shading ){
var fps = 30;
var ctx = canvas.getContext('2d');
var w = canvas.width, h = canvas.height;
var od = ctx.getImageData(0,0,w,h).data;
// var ct = 0, st=new Date;
return setInterval(function(){
var id = ctx.getImageData(0,0,w,h);
var d = id.data;
var now = (new Date)/period;
for (var y=0;y<h;++y){
var lastO=0,shade=0;
for (var x=0;x<w;++x){
var px = (y*w + x)*4;
var o = Math.sin(x/wavelength-now)*amplitude*x/w;
var opx = ((y+o<<0)*w + x)*4;
shade = (o-lastO)*shading;
d[px ] = od[opx ]+shade;
d[px+1] = od[opx+1]+shade;
d[px+2] = od[opx+2]+shade;
d[px+3] = od[opx+3];
lastO = o;
}
}
ctx.putImageData(id,0,0);
// if ((++ct)%100 == 0) console.log( 1000 * ct / (new Date - st));
},1000/fps);
}
</script>
</head><body>
<canvas id="flag"></canvas>
</body></html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment