ZIM - Code and Learn Coding with ZIM for JavaScript and HTML Canvas with CreateJS


ZIM Retina is here which makes ZIM vector crisp and look amazing! One change with Retina, is that the Mouse Event object mouse position needs to be divided by the stage scale:

stage.on("stagemousedown", function(e) {
   var x = e.stageX/stage.scaleX;
   var y = e.stageY/stage.scaleY;

To avoid this, we have provided mouseX and mouseY properties on Frame that include the scale adjust. Use these as follows:

stage.on("stagemousedown", function() {
   var x = frame.mouseX;
   var y = frame.mouseY;
Many ZIM examples and videos use the zim namespace - for instance:

var circle = new zim.Circle();

This is no longer required so you can just use:

var circle = new Circle();

Another example is zim.rand(20) can now be just rand(20). See the news post.
You can chain almost all ZIM methods. For example:

var circle = new Circle()

Note the semi-colon is at the end. Putting these on multiple lines allows you to comment out individual commands for testing. Do NOT chain the CreateJS on() method for events and do NOT chain properties. ZIM provides a number of equivalent chainable methods like:

pos(), loc(), mov(), sca(), alp(), hov(), rot(), reg(), ske(), tap()

New methods have been added and old ones adjusted too chain such as

cur(), sha(), cache() and setMask()

Do NOT use scale() as it conflicts with CreateJS 1.0 but rather use sca(). See the Bubbling video.

In general, to confirm that a ZIM method returns the object, check at the bottom of the docs for that method under the RETURNS section. If it says returns obj for chaining, then you are good to chain!
Configuration Objects are object literals { } that hold properties that match the parameter names for classes and functions. The ZIM DUO technique allows us to pass in parameters individually or as a single parameter that is a configuration object. For example:

// traditional parameters in order:
var rect = new Rectangle(100, 100, red, null, null, 20);

// or as a configuration object:
var rect = new Rectangle({width:100, height:100, color:red, corner:20})

Configuration Objects can be clearer and can be considerably shorter. Also, the order of the properties in the configuration object does not matter. On the other hand, if you are using only the first couple parameters, configuration objects could take longer to type.

RECOMMENDATION: switch between the two depending on the situation. If you need a parameter that is many parameters along, then a configuration object will be better. If you are using a few parameters in order, then traditional parameters are fine.

See the Parameter sections of the ZIM Docs to see if a class or function accepts ZIM DUO. You can also make your own classes and functions work with configuration objects by using zob.
As of ZIM OCT (8) STYLE can be used to define default values for DisplayObject (shapes, components, etc.) parameters:

STYLE = {corner:0, backgroundColor:yellow};

All DisplayObjects will have these styles. You can style a type of object and these will override the general styles:

STYLE.type = {Button:{corner:20, scale:2, bacgkroundColor:"ignore"}};

Now, Buttons will have corners of 20 and be scaled twice as big. The Buttons will also ignore any previous backgroundColor style so they will be the original default (orange).

You can style a group of components and these styles will override the earier styles:

STYLE.group = {customize:{center:true, transform:true}};
new Button({group:"customize"});

The Button will have transform tools applied along with the other styles. You can add any number of objects to a group and objects can be part of more than one group with a comma separated string. Other functions can be applied with styles too, read the STYLE Docs for more features.

Any values applied through parameteters of the component will override the previous styles. You can also set ignoreStyles to true to ignore all styles for the component.

You can animate, wiggle, move, add, centerReg and more with style. You can also provide ZIM VEE values such as an array of options to pick:

color:[red, purple, green], // random
x:series([100,200,300]) // applied in order

The above styles would probably be written all in one assignment:

   color:[red, purple, green],
      Slider:{step:1, useTicks:true, alpha:.5}
      customize:{center:true, transform:true},
      homePage:{outline:true} // apply outline() to all members of this group
ZIM loop() is an easier format than a traditional for(var i=0; i<10; i++){} loop. Here is the format - which matches the familiar event call:

loop(10, function(i) {
  zog(i); // 0-9

There are lots of extra features too. Here are ways to loop through arrays, objects and containers. In the container example we loop through backwards which is important when removing children:

var letters = ["A", "B", "C"];
loop(letters, function(letter) {
  zog(letter); // "A", "B", "C"

var person = {age:20, job:"farmer", greeting:"yo"};
loop(person, function(property, value) {
  zog(property, value); // age 10, job farmer, greetings yo

var monsters = new Container(); // then fill with monster Bitmaps, etc.
loop(monsters, function(monster) {
  if (monster.growl) monster.removeFrom(monsters);
}, true); // true loops backwards

See ZIM Docs for more details including start and end values, continuing or breaking from a loop, more parameters, etc.
ZIM Frame() can scale to a window keeping proportions or fit full window with no scaling. See the Frame page for the templates. Frame can also fit in an existing HTML tag and act just like an image - except an interactive image! You can use multiple frames on the same page.

Frame can be used to load assets in its asset parameter:

var frame = new Frame({assets:"asset.jpg", path:"path/"});
frame.on("ready", function() {
  // in template, frame.stage is stored in var stage

OR at any time in your code with frame.loadAssets():

frame.loadAssets(["pic.png", "sound.mp3"]);
frame.on("complete", function() {

There are more options (such as techniques for multiple loadings) and events when loading - see the ZIM Docs.
ZIM started off with special colors stored on the Frame - frame.green, frame.blue, etc. These have become very well used and there are times the colors are needed before the Frame loads. So, now the colors are available on the ZIM namespace or GLOBALLY if the namespace is not required.

green, orange, blue, pink, brown, yellow, purple, red

As well as shades such as:

dark, darker, light, lighter, grey, tin, silver, white, black, faint, clear

We tend to use these in ZIM examples but any HTML/CSS string color will do such as:

"red", "#CC0000", "#333", "rgba(0,0,0,.2)", etc.

COLOR CHANGES: as of ZIM OCT (8) color parameters across the components have changed:
In many of the earlier ZIM examples and videos, color was the background color and the text color could only be set through a custom Label. This has changed many of the parameter names and the order of the parameters in some places. All changes can be found in the ZIM Docs Updates Page
ZIM is over 200K in size and growing but you can easily use Distill to create a minified file of only the ZIM code that you are using. In your scripts, before you call ZIM Frame, add the following:

DISTILL = true;

This starts a recording of function numbers. When your code is done (i.e. in a click event function) add the following:


At this point, a coded list of all the functions that have been used are displayed in the console (F12). Copy this list and go to the Distill page where you can paste them into the form and submit to receive the distilled minified code - and non-minified code for your reference. You can then paste this code in a remote JavaScript file and call it from your page instead of the full ZIM cdn link:

<script src="remote.js"></script>

Or load the code in between script tags. Here are some Examples and the Docs.
It is beneficial to keep up with changes. The ZIM News section has two main links - the Bubbling videos (started March 2017) and Blog (started March 2016) both of which highlight new features. Bubbling shows features that were added or changed since the end of the ZIM Bits series of 64 code tutorials and after the ZIM Capture video tutorials both found in the ZIM Learn section. A look through the Bubbling videos titles is a quick way to summarize changes (this list as of Oct 2017):

Transform | Noise & Generative Art | Canvas Accessibility | Optional Namespace | ZAP Code Sharing | Multitouch Gesture | Badges Tutorial | New Site for ZIM VEE | Code Zero | SoundWave Frequencies | Documentation Changes and Overview | Lessons | StageGL | Blobs & Beziers! | Ticker | Particle Emitter | Changes in ZIM 5 | ZIM VEE and ZIK | Animate Calls | TextArea | Image Loader | Window Resize | Physics Workshop | Asteroids Workshop | ANIMATE Constant | FPS Meter | Leader Board | GamePad Support | Motion Controller | Accelerator! | Dynamo! | Sprite Updates! | Animation Series | Chaining | Bubbling Series

Specific and complete changes in the ZIM code can be found in the Updates page which goes hand in hand with the updates of the Docs. These show the version numbers of ZIM in major.feature.fix format: Here is a snip of an Updates example where an IMPROVEMENT and a BREAK have been noted:

ZIM 6.3.2
Added split property to Parallax object to center the input value IMPROVEMENT
BREAK Adjusted Parallax parameter order to layers, damp, auto, stage

You may consider updating old code for improvements and if you do update, note that any breaks may require adjustment to old code - usually in the order of parameters.
When you are coding, sometimes things do not show up. Here are some reasons why that might happen: This last tip is the ZEN FIVE MINUTE rule of debugging. If you have been trying to fix something for more than five minutes - no matter what - confirm that you are viewing the file that you are updating.
Often we need to test if objects are hitting. This almost NEVER happens when the code first loads. Usually it happens in a function in one of three places:
  1. Ticker.add(function(){});
  2. object.on("pressmove", function(){});
  3. object.on("pressup", function(){});
The first will check all the time and is good when the various targets are moving on their own. The second is good for when moving an object with a mouse or a finger and the others objects are not moving. The last is good for checking only when you drop on object - for instance, throwing an object in a garbage can. Here is an example of the third:

var ball = new Circle(20).center(stage).drag();
var can = new Rectangle(100,200).loc(100,100);
ball.on("pressup", function() {
  if (can.hitTestCircle(ball)) {

WARNING: we could use ball.hitTestRect(can) but the ball is smaller and it could fit inside the bounds of the can. The hitTestRect() checks to see if the shape of the object the method is placed on is hitting points around the bounding box rectangle. By default, it checks points at the corners of the bounds and one point in the middle of the bounds. Even if we increase the points around the edge of the bounds (with the second parameter), the small circle could be dropped inside the can and not even touch the edges or the exact middle. So the general rule when using hitTestRect() and hitTestCircle(), is put the method on the BIGGER object and test against the points on the Circle or Rectangle of the smaller object with the smaller object in the round brackets - hence, can.hitTestCircle(ball);

OPTIONS: there are other types of hitTests but for the most part, hitTestRect() and hitTestCircle() will be the most popular unless you have two rectangular shapes and then use hitTestBounds() or two circles and then use hitTestCircles(). These last two are very fast as they use equations. The fastest way to test if the mouse (or any object) is over a cell in a grid is with hitTestGrid() - see Docs. This also uses a mathematical calculation rather than comparing color/point based intersection which is used by a mouseover event. See the ZIM Bit or the ZIM Capture on hitTests.

There is also hitTestPath that tests the shape of the object against a Squiggle or a Blob.

HITTING TOO MANY TIMES! If your hitTest keeps telling you it is hitting and you only want to know once... for instance, to play a sound or add 1 to a score, etc. then you may end up playing the sound over and over very quickly or adding too much to your score. You will need to either:

1. Remove one of the objects so they are not hitting:
    if (ball.hitTestRect(rect) {
2. Remove the Ticker or event that is calling the hitTest:
    var ticker = Ticker.add(function(){
      if (ball.hitTestRect(rect)) {
  // OR
    var mousemoveEvent = stage.on("stagemousemove", function(e){
      ball.loc(e.stageX, e.stageY);
      if (ball.hitTestRect(rect)) {
3. Use a check variable (just some logic!):
    var hitCheck = false;
    ball.on("pressmove", function(){
      if (!hitCheck && ball.hitTestRect(rect)) {
        hitCheck = true;
    // you may need to set hitCheck to false some time later
    // if you want to test for another hit! ;-)

MULTIPLE OBJECTS: Often we want to test if something is hitting multiple objects. To do this, put the objects in a Container, loop through the container in the Ticker or event function and test each object:

  var circles = new Container().addTo();
  loop(20, function(){
    var circle = new Circle(20, green).loc(rand(stageW), rand(stageH), circles);
    circle.collected = false;
  var collector = new Rectangle(50, 100).center().drag();
  collector.on("pressmove", function() {
    circles.loop(function(circle) {
      if (!circle.collected && collector.hitTestCircle(circle)) {
        circle.collected = true;
        score.text = Number(score.text) + 1;

REMOVING: when looping through a container or an array and removing an object, for instance, if the object that the collector hits is removed, then you MUST loop in reverse. This will make sure that the index numbers remain the same otherwise you will get intermittent errors. To loop backwards use true as the next parameter value in the loop:

  collector.on("pressmove", function() {
    circles.loop(function(circle) {
      if (collector.hitTestCircle(circle)) {
  }, true); // the true makes loop loop in reverse

There are a variety of ways to add and position objects. Here is an example https://zimjs.com/positioning/. You can also use x, y, regX and regY properties - but generally, we use the following chainable methods:
  1. addTo(container, index, localToLocal)
    • use to add to a container at current x and y
    • note: objects, when created, have an x and y of 0
    • default container is stage - can set index
    • keeps visual positon when changing containers

  2. center(container, index, add)
    • use to center on and add to container
    • default container is stage - can set index
    • can choose not to add

  3. centerReg(container, index, add)
    • use to center registration, center on and add to container
    • default container is stage - can set index
    • can choose not to add

  4. loc(target|x, y, container, index, add, localToLocal)
    • use to place object at the location of a target object
    • or use to locate the registration at an x and y
    • default container is stage - can set index
    • can choose not to add

  5. pos(x, y, horizontal, vertical, container, index, add, reg, regX, regY)
    • NOTE: updated in ZIM 10.6.0 to use horizontal and vertical parameters
    • horizontal can be LEFT (default), CENTER / MIDDLE, RIGHT constants
    • vertical can be TOP (default), CENTER / MIDDLE, BOTTOM constants
    • use to add to container and to easily position around edges or from center
    • setting RIGHT will position right side of bounding box from right side of container
    • setting BOTTOM will position bottom side of bounding box from bottom of container
    • setting CENTER will center object then move the amount specified in x or y
    • default container is stage - can set index
    • can choose not to add
    • set reg to true to position the registration point
    • ** many examples use the old registration point pos()
    • ** the new pos() will work the same way for reg(0,0) objects
    • ** but will work differently for other registrations or rotated objects
    • setting POSREG = true; will default all pos() to reg based
    • but would recommend using loc(x,y) for registration positioning

  6. mov(x, y)
    • use mov() to set relative position
    • does NOT add to a container

  7. reg(x, y)
    • use reg() to change the registration point
    • the object will appear to shift
    • yet its x and y values will remain the same
    • does NOT add to a container

The following code tools are available to help position objects:

  1. place(id)
    • use place() to pick up object and place
    • the console (F12) will show location
    • hard code with pos() in code and delete place()

  2. placeReg(id)
    • use placeReg() to set registration point
    • the console (F12) will show location
    • hard code with reg() in code and delete placeReg()

  3. new Grid(obj, color, percent)
    • tool to see absolute location
    • add a Grid to a container obj (default stage)
    • use the cursor to find x and y values
    • use pos() in code to apply distance
    • set percent to false to see pixels
    • or press the p key to toggle
    • remove the Grid when done

  4. new Guide(obj, vertical, percent)
    • tool to see relative location
    • add a Guide to a container obj (default stage)
    • can use vertical and horizontal
    • use the cursor to find x and y values
    • at a distance from the guide
    • use mov() in code to apply distance
    • set percent to false to see pixels
    • or press the p key to toggle
    • remove the Guide when done
Browsers have a console (F12) that can be used by developers to see what is happening in their code. The console is not seen by the end user - although, if they know how, they can view it. There are also debuggers but these are often not needed. We can zog() helpful messages to the console as we code. zog() is just short for JavaScript's console.log().

If you are just starting to code, it is a good idea to test often. Every time you make a function, the first thing you do should be to zog("functionName"); inside the function to make sure the function is running. Here are a few examples of where we might use functions:

function test() {
  zog("test"); // will show test in the console when function runs
// this function above will not run until it is called:

object.on("click", function() {
  zog("clicked"); // runs when object is clicked

  call:function() {
    zog("animation done"); // runs when animation finishes

Ticker.add(function() {
  zog("ticking"); // runs at the frame rate - very fast!

interval(1000, function() {
  zog("interval"); // runs every second

timeout(500, function() {
  zog("timeout"); // runs once after half a second

loop(10, function(i) {
  zog(i); // shows 0-9 as we loop

In all of these, we would want to make sure the function is running before we start coding inside the function. If we do not, we sometimes will think that our code inside is broken - when really, it is just that the function is not running.
Indenting is very important - it is how we organize our code. Imagine taking a book and making paragraphs from every four sentences. You can still read the book, but you will be left puzzled quite often.

Indenting is equivalent of putting things in boxes - boxes within boxes. This lets us see the code at multiple levels when we are planning or debugging. We can easily skip over whole sections just by looking at the indenting. Indenting is the product of hierarchy - of abstraction - a key concept in coding and in life.

There are very easy and consistent rules for indenting. These are somewhat clouded by chaining but here they are:
  1. Indent inside { } when on multiple lines - think of these as a box.
  2. Indent using a single tab (not two or three - not spaces)
There... not so hard! Here are some extras:
  1. Indent when chaining on a new line but stop indenting at the end of the statement;
  2. If your indents are too small, change them in your preferences
Look at the code examples on this page. Or look at every single example on the ZIM site - over 1,000,000 lines of code. You will not find a single indent out of place. That is the importance of indenting. "You will code more efficiently by perfecting indentation" - Dr. Abstract.

This code was received in Slack. In general, the indenting is not that bad. The first line could have been a copy and paste error into Slack. And the different number of characters for the indents come from copying from different files - but would highly recommend fixing.

Below are the areas of concern. These will undoubtedly be fixed at some point - but the sooner the better. As a rule - do not go forward until your indenting is fixed. EVER. Once again, not too bad... certainly seen worse. But even the few indent errors here make the code hard to read.

  1. To fix a different indent size, select the lines and shift tab until they hit the edge then tab into the right position.
  2. When copying (or cutting) and pasting, paste at the same tab indent as when copying or cutting. If you cut from the very left, paste at the very left. If you cut 4 tabs in then paste 4 tabs in.
  3. In many editors (like Atom and Sublime) sitting at a bracket will show you the matching bracket.
  4. Some editors will draw lines connecting tabs and some will provide collapsible blocks.
  5. Remember to set your tab indent to at least 4 characters. The default 2 characters is too small which encourages double tabbing or adding spaces - bad habbits!
ZIM is built on CreateJS at https://createjs.com and so all CreateJS documentation applies to ZIM.

ZIM Containers extend CreateJS Containers and many of the ZIM Display objects extend ZIM Containers. This means, the ZIM objects get all the CreateJS methods, properties and events like on(), setBounds(), x, y, rotation, alpha, mousedown, mouseover, mouseout, pressmove, pressup, etc.

If we have a CreateJS display object such as a Container or Shape that comes from Adobe Animate, etc. then we can give this object all the ZIM display methods by using the zimify(CreateJSObject) global function. This adds drag(), animate(), all the ZIM hitTests, center(), centerReg(), pos(), mov(), etc. to the CreateJS object.

It should be noted too that ZIM objects have a width, height, widthOnly and heightOnly properties. These scale the object to give the desired width and height. They leave the bounds as originally set:

var rect = new Rectangle(100,100).center(stage);
rect.width = 200; // scales the rect by 2 in both the x and y
zog(rect.width); // 200
zog(rect.getBounds().width); // 100
zog(rect.scaleX, rect.scaleY); // 2, 2

When you are creating a Container or a Shape you have the choice of setting the width and height as parameters as you make the object. You can optionally set the boundsX and boundsY and the width and height. You can also let the container make its own bounds based on its contents by leaving the container parameters as null. And of course, you can get and set the bounds at anytime using getBounds() and setBounds(). Setting the bounds to null will have the container automatically calculate its bounds. For ZIM center() and centerReg() and various hitTest methods it is often helpful or necessary to have the bounds set.
Use the console (F12) to see any errors in your code - they are RED and will show a message and a line number. Sometimes the message does not make sense, or the line number seems strange. Here are some tips: In general, if you can't figure out something then simplify. Comment out code until it works again. Or even try the problem code in a new file. Also remember to save your file and check to see you are testing the right file.
We are here and love to help. There is no question too small and no question too big. Here is an invite to the ZIM Slack Team. It just takes a moment to sign up to Slack and it is all online. Many companies are using Slack for internal communication. Slack is being used as forums for software support, educational communications, etc. Here are the ZIM Slack channels - it helps to post in the relevant channels but you will find us all very friendly - so no worries:
  • Examples - view and show projects
  • General - posts that don't fit in other channels
  • Releases - ZIM announces each release here
  • Questions - ask how to do something
  • Random - chit-chat - maybe not about ZIM
  • Requests - what would you like to see in ZIM