I'm braindead. So I decided no to go into philosophical discussion - rather checked the Canvas API the first time. Yeah, I know it's already too old. Anyways. Canvas is so simple anybody can learn the basics in 5 minutes. To make a little sense I decided to make a silly screensaver like animation - a curve that bouncing on the screen and leaves a frame.
The idea is very simple. A bezier curve has a start context point, 2 control points an an end point.
Fig.: Bezier curve
First you need a nice HTML5 template like this:
<!doctype html> <html> <head> <script type="text/javascript"> </script> </head> <body onload="onBodyLoad();"> </body> </html>
For the canvas you need the dom element in the body:
<canvas id="screen" width="640" height="480"></canvas>
The canvas has a drawing context, so let's create a variable for it:
var ctx;
This context can accept our commands later. We need to access our canvas' boundaries somehow:
var boundaries = {
w: 640,
h: 480
};
We set the timer interval to 0.01 second:
var interval = 10;
Set the average speed of a point:
var speed = 10;
Then we generate 4 random points with random vectors:
var number = 4;
var items = [];
for (var i = 0; i < number; i++) {
items[i] = {
point: {
x: Math.random() * boundaries.w,
y: Math.random() * boundaries.h
},
speed: getRandomSpeedVectors(speed)
}
}
To make all speed the same but with a different angle we use some math to generate the X and Y speed values:
function getRandomSpeedVectors(speed) {
var speed_x = Math.random() * speed;
return {
sx: speed_x,
sy: Math.sqrt(Math.pow(speed, 2) - Math.pow(speed_x, 2))
};
}
To make point updates easy we add a new method to the JavaScript Object prototype:
Object.prototype.applyWorld = function(speed_vector, boundaries) {
if (this.x + speed_vector.sx >= boundaries.w || this.x + speed_vector.sx <= 0) {
speed_vector.sx *= -1;
}
if (this.y + speed_vector.sy >= boundaries.h || this.y + speed_vector.sy <= 0) {
speed_vector.sy *= -1;
}
this.x += speed_vector.sx;
this.y += speed_vector.sy;
};
This function will be available on the object method level and can handle 1 state change on a point. That's enough to make the point moving.
Now we need something that actually handles 1 step for all the points and draw the curve on the canvas:
function loop() {
ctx.clearRect(100, 100, boundaries.w - 200, boundaries.h - 200);
ctx.beginPath();
ctx.moveTo(items[0].point.x, items[0].point.y);
ctx.bezierCurveTo(
items[1].point.x, items[1].point.y,
items[2].point.x, items[2].point.y,
items[3].point.x, items[3].point.y
);
ctx.stroke();
for (var idx in items) {
var item = items[idx];
if (!item.point) {
continue;
}
item.point.applyWorld(item.speed, boundaries);
}
setTimeout(loop, interval);
}
It also calls itself so that makes it an animation. And finally we have to initialize the canvas and start the animation, so let's hook into the body onload event:
function onBodyLoad() {
var canvas = document.getElementById('screen');
if (!canvas.getContext) {
return;
}
ctx = canvas.getContext('2d');
ctx.lineWidth = 6;
ctx.strokeStyle = 'rgba(33, 66, 99, 0.5)';
loop();
}
That's it. You can find the demo here: https://dl.dropbox.com/u/2629592/canvas_screensaver.html. For the source code check the Github repo: https://github.com/itarato/CanvasScreensaver/blob/master/index.html.
---
If you have a more efficient way to do it (I bet you have) please let me know.
Peter
---
If you have a more efficient way to do it (I bet you have) please let me know.
Peter

No comments:
Post a Comment
Note: only a member of this blog may post a comment.