# crazy bubbles
In this example you can see a series of circles moving randomly and colliding with the edges of the
box that contains them. It is an example of how user requestAnimationFrame()
to perform a
Javascript controlled animation.
edit in codepen.io (opens new window)
We will now explain step by step how to create this animation.
# Import gySVG
The first step, if we haven't already done so, is to import the Graphery SVG library. In our case, we've
chosen to include the code within a script type=module
and we'll use the import
expression.
see: load gySVG
# Create the SVG
To create the graph we are going to use gySVG()
and we are going to configure the viewBox,
the width and height attributes.
see: SVG Element, .viewBox,
# Edge rectangle
The edge limits are defined with simple rentable:
# Create circles
We put 10 circles with random values and put the circle object into an Array.
The custom attributes speed_x()
and speed_y()
work
The custom speed_y
and speed_y
attributes work just like any other gySVG member, but we have
actually created them dynamically to store the information about the speed of the bubble
movement in the X and Y axis. gySVG has the virtue of being able to create any custom attribute
we need by simply calling the function with the name that we want to use. It will automatically
create an attribute with the name we have chosen, and we can set its value with .name(value)
and
get it value with .name()
.
# Add animation
With requestAnimationFrame()
we can update the element positions to perform an animation and
request that the browser calls our function to update an animation before the next repaint.
# The complete code
If we put all these steps together this is the example's code:
import gySVG from 'https://cdn.graphery.online/svg/1.0.0/module/index.js';
const svg = gySVG ().viewBox (0, 0, 500, 300).width (500).height (300);
const rect = svg.add ('rect').x (1).y (1).width (498).height (298)
.fill ('none').stroke ('grey').stroke_width (2);
const circles = [];
for (let n = 0; n < 10; n++) {
circles.push (
svg.add ('circle')
.cx (100 + Math.random () * 150)
.cy (50 + Math.random () * 100)
.r (Math.random () * 20 + 5)
.speed_x (Math.random () * (n % 2 === 0 ? -0.015 : 0.02))
.speed_y (Math.random () * (n % 2 === 0 ? -0.02 : 0.015))
.fill (`hsl(${ 255 * Math.random () }, 100%, 50%, 0.5`)
);
}
svg.attachTo ('#content');
let prev = 0;
function step (timestamp) {
if (prev === 0) {
prev = timestamp;
}
const elapse = timestamp - prev > 66 ? 66 : timestamp - prev;
prev = timestamp;
circles.forEach (c => {
const cx = c.cx ();
const cy = c.cy ();
const r = c.r ();
let speedX = c.speed_x ();
let speedY = c.speed_y ();
let moveX = r * speedX * elapse;
let moveY = r * speedY * elapse;
if (
(cx + r + moveX >= 500 && speedX > 0) ||
(cx - r + moveX <= 0 && speedX < 0)
) {
c.speed_x (-speedX);
}
if (
(cy + r + moveY >= 300 && speedY > 0) ||
(cy - r + moveY <= 0 && speedY < 0)
) {
c.speed_y (-speedY);
}
c.cx (cx + moveX);
c.cy (cy + moveY);
});
requestAnimationFrame (step);
}
step (0);
← spirograph sleepy dog →