Controlling the Canvas with JavaScript

How you can make the Canvas do amazing things!

Welcome readers from ◎ Your Guide to Coding Creativity on the Canvas

We are using the ZIM JavaScript Canvas Framework which is easily to use and get started with! Find out more with ◎ Your Guide to Selecting a JavaScript Canvas Library or Framework.

Controls operate on existing objects. We have discussed page and layout controls in ◎ Your Guide to Responsive and Adaptive design on the Canvas and accessibility controls in ◎ Your Guide to Accessibility on the Canvas with JavaScript.

We will now look at the rest of the main controls in ZIM:

    move objects with mouse, key and gamepad
    emit objects as particles
  • PEN
    dynamically draw
    move objects with a 3D effect
    animate backgrounds and Sprites
    3D for side-by-side viewers and jumps
    make sound and animate to sound
    move or rotate an object in 3D
    make a world with forces, collisions and more!


A MotionController() will control whatever DisplayObject you pass to its first parameter. Let’s code together with this handy Online Editor. You are one click and copy away from coding! Type or copy and press TEST:

const car = new Rectangle(120,60).centerReg();new MotionController(car);

Press anywhere to make the car slide (we will fix that soon) to that location.

The MotionController has many parameters. See the ZIM Docs. There are bounds, rotate, flip, firstPerson, speed, and more.

The second parameter is the type of input. Here are the options:

  • mousemove
    target follows mouse movement
  • pressmove
    target jumps to mouse then follows while pressing
  • pressdrag
    target follows mouse if pressed on and then dragged
  • keydown
    keys control the target (see map parameter)
  • gamebutton
    gamepad buttons control the target
  • gamestick
    gamepad stick(s) control the target
  • swipe
    swipe to control the target
  • follow
    mousedown and hold and use Frame.follow()
  • manual
    set a custom input and use convert(), x and y
// make a better car!
STYLE = {corner:10};
const car = new Rectangle(120,60).centerReg();
new Rectangle(50,50,yellow).center(car);
new MotionController({

Here is the ZIM MotionController demo page where you control a butterfly sprite with mouse, keys or game controller on the canvas!

As with the rest of the controls, this could be coded manually but it is the type of code that is used in many games, puzzles, apps, etc. — we call them Zapps. So we code them once and provide them as controls. Let’s see some more controls!


With the Emitter(), we emit a bunch of copies of whatever DisplayObject we pass to its first parameter. There are parameters to handle the interval (how fast), life (how long), force, gravity, wind, properties can we animate, etc. See the ZIM docs.

CLEAR and then type or copy this and TEST:

new Emitter( new Poly(200,6,.6,yellow,dark) ).center();

Let’s see what we can do with a few parameter changes. We can use the ZIM VEE values on the Poly to make each star different. We will also switch to ZIM DUO for the parameters. See ◎ Your Guide to Conveniences when Coding on the Canvas to learn about ZIM VEE and ZIM DUO.

new Emitter({
obj:new Poly({
radius:{min:50, max:100},
pointSize:{min:.5, max:.8},
color:[yellow, orange, red],

And now, let’s play with the Emitter parameters:

new Emitter({
obj:new Poly({
radius:{min:50, max:100},
pointSize:{min:.5, max:.8},
color:[yellow, orange, red],
force:{min:4, max:8},
angle:{min:-90-20, max:-90+20},
time:{min:1, max:3},


The ZIM Pen() will help you draw. We made a complex app called GenPen to explore possibilities. Wow! How exciting.

Let’s make a drawing app in a couple of lines. CLEAR, type and TEST:

new MotionController({
target:new Pen().addTo(),

The default MotionController speed is 10 so it takes the pen a while to catch the mouse. Let’s set the speed to 100. Another setting to consider is damping. Damping is how quickly an object moves to its target and can be used to make smoother motion. Damping is being applied to the MotionController and the Pen. We will turn damping off on the MotionController with damp:1 and leave the damping at the default for the Pen.

Let’s add a black Rectangle to the background. Normally, this is done with the color parameter of the Frame, but here we are in an editor that adds the stripes at the back.

WARNING: a MotionController will by default, not be activated with a press on another object. This allows the user to properly press interface like buttons without the controlled object moving to the button. On any background objects you want to activate the MotionController either add them to mousedownIncludes or call their noMouse() method.

const rect = new Rectangle(stageW, stageH).addTo();
new MotionController({
target:new Pen({
size:{min:10, max:80}


Parallax is when things move at different speeds to give a sensation of depth. Usually, things in the background move slower than things in the foreground. Try looking far away. Now, hold your hand in front of you and shift your head left and right. Your hand appears to move more (faster) than the background.

With ZIM Parallax() existing DisplayObjects are added to layer objects along with which property to change and how much to adjust. The input for the change can also be set. This defaults to mouseX but can be mouseY, scrollX, scrollY or a custom input. You then pass the layer objects to Parallax() in an array as the first parameter. Alternatively, the add() method can be used to add them individually.

CLEAR your code, copy and paste this and press TEST:

// make assets to move around
// these could be pictures, shapes, containers, etc.
const back = new Rectangle(800, 200, yellow).center();
const mid = new Rectangle(400, 200, green).center().mov(0,30);
const front = new Circle(80, red).center().mov(0,60);
// make Parallax object
// here we move with mouseX and mouseY
const parallax = new Parallax([
{obj:back, prop:"x", propChange:50},
{obj:back, prop:"y", propChange:40, input:"mouseY"},
{obj:mid, prop:"x", propChange:125},
{obj:mid, prop:"y", propChange:80, input:"mouseY"},
{obj:front, prop:"x", propChange:200},
{obj:front, prop:"y", propChange:100, input:"mouseY"}

There is also page scroll parallax. Here are some examples:


The ZIM Scroller() takes a DisplayObject and animates it horizontally or vertically as a repeating background. Here is a simple example:

In the above example, the Sprite and the Scroller are running at one speed. We have put a system in place with a Dynamo and Accelerator to allow the user to change the speed.

A Dynamo() lets you set a percentSpeed on a Sprite so you can speed it up and slow it down. An Accelerator() lets you collect Dynamo and Scroller objects to set their percentSpeed together. Pass the accelerator to a MotionController() and the user can speed up and slow down the whole scene. This is pretty amazing!! Move your cursor (or press your finger) to the left and right in this example :

// create an accelerator which will move all things proportionally
// use a Dynamo to allow the Sprite to have a dynamic speed!
// can use more backgrounds and foregrounds to do parallax
const accelerator = new Accelerator([
new Scroller({backing:background, speed:1.5}),
new Dynamo({sprite:spaceGuy, reversible:false})
new MotionController({

Pop on over to YouTube to watch us code a dynamic sprite scene in Five minutes! Well, we cheated in this one with two five minute episodes!



Here are a couple controls you do not see often! ZIM VR() will copy a scene to an adjacent scene and add depth shifting so they look 3D when viewed with a side-by-side viewer like Google Cardboard or Samsung Gear. Dr Abstract loved the 3D effect example… use a viewer!

// prepare content inside one container
const content = new Container(stageW/2, stageH);

// this background tile has no depth or is at "screen" depth
// there will be no depth shift and no parallax
new Tile(new Rectangle(10,10,light), 20, 1, 10)

// these rectangles are given depth using the dep() method
// the rectangles will be shifted in the x by VR
// centerReg the objects for proper parallax
var box = new Rectangle(50,50,green)
new Rectangle(70,70,clear,blue,5)

// 1. this just shows content in 3D with no motion:
const vr = new VR(content).addTo(stage);

// 2. this will move when the head is turned (device is rotated)
// but with no parallax:
const vr = new VR(content, 160, 400).center();

// 3. this shows parallax when the head is turned
// but with no positional movement:
const vr = new VR(content, 0, 400, 2, 60).center();

// 4. this shows motion and parallax as the head is turned:
const vr = new VR(content, 160, 400, 2, 60).center();

The second effect in this section is ZIM Portal() which was a fun little experiment to go from one place to another (or page to another). Try out the ZIM Portal Demo Page.

// portalObject is the object to act like a portal
// lands is a Container that holds DisplayObjects
// such as pictures or interactive scenes
var portal = new Portal(portalObject, lands);


ZIM Synth() lets you play a sound recorded by an online tool or play tones that you can manipulate. ZIM SoundWave() lets you capture sound frequencies so you can animate to sound! Both wrap the HTML 5 WebAudio API. The ZIM Synth Demo Page is an example with both controls in the same app with the SoundWave in the middle circle. There is also a ZIM SynthPad example where you can multitouch different sounds.

Let’s code a Synth together in our Online Editor. CLEAR, type or copy and TEST the following to hear a tone:

// apps must be interacted with before playing soundconst synth = new Synth();
new Button({label:"PLAY", corner:0})
function playTone() {

Change the tone() to add some WAH to a Square wave:

function playTone() {

Here are Bubbling and Explore videos that take you through all sorts of options for the ZIM Synth and the ZIM Docs entry for Synth. There are also some examples of the Synth play() method in the ZIM Sounds example.

ZIM SoundWave() lets you animate to sound frequencies from songs, ZIM Synth or a microphone. See the ZIM Docs on SoundWave including links to the classic animated sound frequency bars.

In the Code in Five Minutes SoundWave video we collect data for 40 frequencies. When the SoundWave is ready we make 40 concentric circles with random colors. In a Ticker we call the calculate() method and set the radius of the circles based on the data at the frequencies!

To see how to load sound see ◎ Your Guide to Images, Sounds and Sprites on the Canvas. To see how we made the colors see ◎ Your Guide to Conveniences when Coding on the Canvas.

const soundWave = new SoundWave(40, sound);
soundWave.on("ready", () => {
const circles = new Container();
const colors = [pink, blue, green, orange, yellow];
loop(soundWave.num, ()=>{
new Circle(100, colors).addTo(circles);

Ticker.add(() => {
let data = soundWave.calculate();
circles.loop((circle, i) => {
circle.radius = data[i];


ZIM is a 2D canvas framework but we can bring in and control Threejs. When we do, the ZIM Swiper() is handy for rotating objects. Here is a CodePen example:

In the Pen above we play around with the model so it gets a touch complicated. The Swiper part is easy. We make a Rectangle under the 3D object called swiperRect. We adjust the rotation about the x axis just a little so that we can tilt the phone back. In the example, we also rotate the phone around the y axis and change the pictures every time the front is hidden!

// ZIM Swiper for controlling the rotation of the model
// swipeOn, target, property, sensitivity,
// horizontal, min, max, damp (using default)

new Swiper(swiperRect, phone.rotation, "x", .001, false, -.2, 0);


Physics sets up a world with bodies, forces, collisions and more! We use the Box2D Physics engine that powered Angry Birds. BUT… we made it way more simple in ZIM! We even teach physics to kids.

We are about to add a Physics option to ZIM Kids Slate but for now we can pop over to ZIM Zoo which is a fun place to quickly try out ZIM code. Type this into the Zoo Editor and press VIEW. You will be amazed to find that you can throw around a ball in ZIM and have it bounce off the sides!

// NOTE that we CHECKED the physics checkbox above the editorconst physics = new Physics();
new Circle()

There are all sorts of wonderful things you can do with physics. We have worked in many interactive environments, and this is by far the easiest we have ever had physics. As a matter of fact this makes a falling circle:

new Circle().center().addPhysics()

Here is the ZIM TEN Physics Mini-Site announcing integrated physics and providing examples to guide balls, score goals, part love-beads, count soccer kick-ups and play a following game in cyberspace!

TIPS for Physics on the Canvas with ZIM:

  • Physics can have gravity (side view) with falling things
  • Physics can have no gravity (top view) like a pool game
  • There are static and dynamic bodies
  • Use a force to move things, not x and y animations
  • Use the Physics drag(), not the ZIM drag()
  • Use the Physics contact(), not the ZIM hit tests
  • You can join() things in different ways
  • You can make the Physics world follow an object

This example uses physics to make a cool data visualization:

Here are some more Examples with comments in the code (view source):


Physics can have buoyancy as shown in the famous ZIM Soup!


Scroll up and down the page. We hope that you are inspired to code creativity on the canvas! Many of these topics are considered advanced, yet for the most part, they can be coded in a few lines each in ZIM. This allows you to concentrate on your creativity! What are you going to make? What assets will you use and how will you tell your story?

There is plenty of coding left to do to make art, games, puzzles and apps. We very much look forward to seeing what you make. When you get coding with ZIM, please join us on our Slack Channel. Invite others to code with you. Tell colleagues, friends and family. These controls are nothing short of magical, and there is plenty of magic to go around.

Further reading

This guide is the last of the guides referred to in ◎ Your Guide to Coding Creativity on the Canvas.

The guides have roughly followed the ZIM Skool topics which also relate to the Learn JavaScript with Creative Coding video series. In each of these there is one added lesson. Data. We plan on a future guide about data as well as a future guide on creativity. Until then, for data, there is the added LESSON 09. For creativity, there is the Creativity Framework.

All the best! Dr Abstract.

Follow us on Twitter at ZIM Learn and here is ZIM Learn on YouTube!

Inventor, Founder of ZIM JavaScript Canvas Framework and Nodism, Professor of Interactive Media at Sheridan, Canadian New Media Awards Programmer and Educator

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store