Chrome Experiments

Mar 29 2009 Published by Eneko Alonso under uncategorized

chromeexperiments.com gathers a good amount of very impressive javascript demos, showing the future of the Internet, where javascript intensive sites and application will become more and more common.

My favorites:
Browser ball – bounce a ball between different browser windows
Kaleidoscope – very smooth animation and beautiful colors

No responses yet

Spinning Color Wheel: Mootools + Raphael + SVG

Jan 18 2009 Published by Eneko Alonso under uncategorized

A couple of days ago I was playing at work with the RaphaelJS library to do some image rotation that we may end up using on a new project we are working on. At the end I ended up creating a spinning object with variable speed, similar to this demo I show you here.

Using RaphaelJS it is very easy to embed any image into an SVG object and rotate it. With a little bit of animation, we can set angular speeds and have some fun :)

Spinning color wheel

I have added an acceleration parameter which will make the speed changes very smooth, although it the new speed is very different than the current one, it will take some time to reach it.

See it in action: http://enekoalonso.com/research/color-wheel.php

The code

  1. var ColorWheel = new Class({
  2.   Extends: Thread,
  3.  
  4.   initialize: function(options) {
  5.     this.parent(options);
  6.     this.raphael = Raphael('wheel', 400, 400);
  7.     this.wheel = this.raphael.image('media/svg/colorwheel.svg.png', 0,0,400, 400);
  8.     this.lblSpeed = $('speed');
  9.     this.lblRPM = $('rpm');
  10.     this.lblFPS = $('fps');
  11.    
  12.     $('btnSetSpeed').addEvent('click', function(event) {
  13.       this.setSpeed($('targetSpeed').get('value'));
  14.     }.bind(this));
  15.   },
  16.  
  17.   execute: function() {
  18.     var now = new Date().getTime();
  19.     this.fps = (1000 / (now – this.lastTime)).toFixed(2);
  20.     this.lastTime = now;
  21.  
  22.     if (this.targetSpeed == 0) { // stop
  23.       this.angularSpeed *= 0.99;
  24.       if (this.angularSpeed < 0.1) this.stop();
  25.     }
  26.  
  27.     else if (this.angularSpeed < this.targetSpeed) { // accelerate
  28.       this.angularSpeed = Math.min(this.angularSpeed + this.acceleration, this.targetSpeed);
  29.     }
  30.  
  31.     else if (this.angularSpeed > this.targetSpeed) { // brake
  32.       this.angularSpeed = Math.max(this.angularSpeedthis.acceleration, this.targetSpeed);
  33.     }
  34.  
  35.     var currentRPM = 60*(this.angularSpeed/360)*(1000/|>this.options.interval);
  36.     this.lblSpeed.set('text', 'Angular speed: ' + this.angularSpeed.toFixed(2) + ' deg per frame');
  37.     this.lblRPM.set('text', 'Current speed: ' + currentRPM.toFixed(2) + ' rpm');
  38.     this.lblFPS.set('text', 'Frames: ' + this.fps + ' fps');
  39.  
  40.     this.wheel.rotate(this.angularSpeed);
  41.   },
  42.  
  43.   start: function() {
  44.     this.angularSpeed = 0;
  45.     this.setSpeed($('targetSpeed').get('value'));
  46.     this.acceleration = 0.1;
  47.     this.lastTime = new Date().getTime();
  48.     this.parent();
  49.   },
  50.  
  51.   setSpeed: function(rpm) {
  52.     if (this.stopped) this.start();
  53.     this.targetSpeed = (rpm/60)*(360)*(this.options.interval/|>1000);
  54.     console.log('setSpeed (rpm,anglespeed): ', rpm, this.targetSpeed);
  55.   }
  56. });
  57.  
  58. window.addEvent('domready', function() {
  59.   new ColorWheel({interval:1000/30}).start(); // 30 fps
  60. });

Enjoy!

PS: I took the color wheel from Wikipedia, although I couldn’t figure out how to embed an SVG graphic into a Raphael SVG container.

4 responses so far

Forest demo (was Grass)

Dec 26 2008 Published by Eneko Alonso under uncategorized

I have updated the Grass demo and renamed it to Forest, which I think is a more appropriate environment for the sounds I used. I have done some fixes to the rain loop and I have added some light animations.
Magic Forest demo

No responses yet

Splitting a vector into two vectors 90 degrees apart

Dec 25 2008 Published by Eneko Alonso under uncategorized

I wanted to add something special to the Particle-Balls demo I made. At first, the idea seemed pretty simple: When clicking on a moving ball, split it in two with a 90° angle between them (π/2 in radians). To keep it simple, both balls will have the same size as the original and the same speed.

Vector split

Moving objects

So far, the way I have always animated objects is by storing a 2D position (x, y) and a 2D speed (horizontal speed and vertical speed). If the vertical speed is zero the object will be moving horizontally. If the vertical speed and horizontal are the same, the object will be moving at 45 degrees (π/4) and so on. It is very easy to update the position on every step of the animation according to the speed:

  1. // Speed is the number of pixels per second.
  2. // Interval is the time between calls in milliseconds.
  3. this.position.x += this.speed.x * (interval/1000);
  4. this.position.y += this.speed.y * (interval/1000);

Calculating the moving vector

When I started writing the code to split the ball in two, soon I realized my math was way deep in my memory where I couldn’t find it. Yes, trigonometry had to be involved, since I needed to calculate the angle of a moving ball based on the vertical and horizontal velocity. Then I would add 45 degrees (π/4) to the existing ball and create a clone of it, but subtracting 45 degrees (π/4) from the original angle. Easy, uh?

Let’s see. First we need to get the angle of the vector the object is moving on. This vector is determined by the vertical and horizontal speed, which form a right triangle:

\theta=arctan(\frac{opposite}{adjacent})

Or in Javascript:

  1. var angle = Math.atan2(ball.speed.y, ball.speed.x);

Angle of new vectors

Once we have the angle, we can calculate the angle of the new vectors:

  1. var V1angle = angle + Math.PI/4; // Add 90 degrees
  2. var V2angle = angle – Math.PI/4; // Subtract 90 degrees

2D speeds of new vectors

Once we have the final angles we can calculate the new horizontal and vertical speeds of the new vectors. But first we need Pitagoras to calculate the actual speed of the original vector:

speed=\sqrt{adjacent^2+opposite^2}

In Javascript:

  1. var speed = Math.sqrt(Math.pow(ball.speed.x,2)+Math.pow(ball.speed.y,2));

Given the hypotenuse (speed) and the angle, we can calculate the sides:

opposite=speed*sin(\theta)

adjacent=speed*cos(\theta)

In Javascript:

  1. ball1.speed.x = speed * Math.cos(V1angle);
  2. ball1.speed.y = speed * Math.sin(V1angle);
  3.  
  4. ball2.speed.x = speed * Math.cos(V2angle);
  5. ball2.speed.y = speed * Math.sin(V2angle);

And that is it! At the end, the math is not that complicated, as you can see. But if you haven’t used trigonometry in years, it kind of hurts a little bit when you have to figure it out.

PS: Thanks to my German sister Sarah for your help (we figured it out while having dinner)

One response so far