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


Many ZIM examples and videos use the zim namespace - for instance:

const circle = new zim.Circle();

This is no longer required so you can just use:

const circle = new Circle();

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

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
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(), siz(),
ske(), tap(), hov(), cur(), top(), bot(), ord(), sha()

Other methods can be chained too such as

center(), centerReg(), cache(), setMask(), etc.

Do NOT use
as it conflicts with CreateJS 1.0 but rather use
. 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:
const rect = new Rectangle(100, 100, red, null, null, 20);

// or as a configuration object:
const 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.
There are a variety of ways to add and position objects. See 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
    • unless localToLocal is set to false

  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
    • if target is in another container will still place on target
    • unless localToLocal is false

  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

Each DisplayObject (Circle, Button, Container, etc.) is placed in its container at a certain level (layer) starting with 0 at the back and increasing in index number to the front. This is similar to layers in Photoshop or Flash and to z-index in CSS. When things are added they are placed on top but a specific level can also be given as follows:

new Circle().addTo(container, level);
new Circle().loc(x, y, level);
new Circle().pos(x, y, horizontal, vertical, level);
new Circle().center(container, level);
new Circle().centerReg(container, level);

The following methods and properties are available to set levels:

  1. top()
    • moves object to top of container
    • chainable zim method

  2. bot()
    • moves object to bottom of container
    • chainable zim method

  3. ord(num)
    • moves object relatively up or down
    • ord(-1) moves down a level, ord(-3) down three
    • ord(1) moves up a level, ord(2) moves up two
    • chainable zim method

  4. parent.addChildAt(obj, level)
    • CreateJS method, not chainable
    • note this is on the parent

  5. parent.setChildIndex(obj, level)
    • CreateJS method, not chainable
    • note this is on the parent

  6. parent.getChildIndex(obj)
    • CreateJS method, not chainable
    • note this is on the parent

  7. parent.swapChildren(obj1, obj2)
    • swaps the location of two children
    • note this is on the parent

  8. parent.swapChildrenAt(index1, index2)
    • swaps two children based on index
    • note this is on the parent

  9. parent.removeChildAt(index)
    • removes a child at an index
    • note this is on the parent

  10. parent.sortChildren(sortFunction)
    • sorts children of a container
    • make a function that returns 1,-1 or 0

  11. obj.numChildren
    • read only to find the number of children in container

JavaScript 6 (ES6) is now being used in the ZIM Template, ZIM Skool, CodePen examples, etc. However the earlier examples are ES5 based. Here are the two most common differences:

// 1. Instead of var we use const or let
// const is for always holding the same object
// let is for variables that may change objects (see stageW, stageH below)

const frame = new Frame(); // always the same Frame object

frame.on("ready", () => { // 2. ES6 Arrow Function - short for function(){}

    const stage = frame.stage; // the only object to be stored in stage
    let stageW = frame.width; // stageW changes number objects when window is resized
    let stageH = frame.height; // so width and height are not constants here

    const circle = new Circle().center().drag();
    circle.color = red; // okay to change properties of constant

    frame.on("resize", e => { // arrow functions with one param do not need ()
        stageW = e.target.width; // or frame.width
        stageH = e.target.height; // note we change width and height objects
        circle.loc(stageW/2, stageH/2); // or center() ;-)


ZIM Frame creates a canvas tag, the stage and scales these in a variety of ways. We recommend that you use the frame available on the CODE page - just copy the tempate! See the FRAME page for more templates like Full window, Fit to the window, fitting in an existing HTML tag and act just like an image - except an interactive image! You can use multiple frames on the same page and even overlap frames.

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

const frame = new Frame({assets:"asset.jpg", path:"path/"});

frame.on("ready", () => {
    // in template, frame.stage is stored in const stage

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

// inside your frame "ready" event function
// at any specific time you want to load assets - also see 8. IMAGES below.

    frame.loadAssets(["pic.png", "sound.mp3"]);

    frame.on("complete", () => {

There are more options (such as techniques for multiple loadings) and events when loading - see the ZIM Docs.
Images can be loaded with Frame - see 7. FRAME above. When you view images LOCALLY in a Browser there is a security error that mentions CORS (cross origin resource sharing). The issue will go away when on a SERVER. This is a general (not just ZIM) JavaScript Canvas security for local viewing.

To solve the issue, you can use a Browser package in your editor such as Atom or Sublime. Or start your favourite Browser as follows:

type: about:config into your Browser URL bar
search for security.fileuri.strict_origin_policy and double click it to set it to false

To test locally, find your Chrome icon or shortcut, right click and choose properties
then under Target, adjust your target to include --allow-file-access-from-files (after the quotes)
eg. "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files
** You must always start your first Chrome window from this shortcut

open your terminal anywhere, make sure Google Chrome is currently not running
copy paste this line and hit enter:
open -a "Google Chrome" --args --allow-file-access-from-files

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

const frame = new Frame({assets:"asset.png", path:"path/"});

frame.on("ready", () => {
    const stage = frame.stage;


    // note: if you want two or more copies of the image then use clone()



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.

You can also convert colors and animate between colors:

const faintBlue = convertColor(blue, "rgba", ".5");
new Circle(100, red).animate({color:faintBlue}, 1000);

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
In general, use the on() method to capture events such as:

"click", "dblclick", "mousedown", "pressmove", "pressup",
"mousemove", "stagemousemove", "mouseover", "mouseout"
"ready", "complete", "change", "keydown", "keyup"

This is like the traditional JavaScript addEventListener() but shorter and with a few extra features:

const button = new Button().center();
// the type of event as a string and the function to call
button.on("click", ()=>{
    zgo("https://zimjs.com", "_blank");

// alternatively, using a named function
button.on("click", doClick);
function doClick() {
    zgo("https://zimjs.com", "_blank");

const tile = new Tile(new Rectangle(), 5, 5, 2, 2).center();
tile.on("mousedown", e=>{ // collect the event object in parameter e
    // e.target is the object that caused the event (one of the rectangles)
    e.target.alpha = 0;
    // e.currentTarget is the object on which the event is placed (the tile)
    // do not forget to update stage in events if needed!

let keyEvent = frame.on("keydown", e=>{
    zog(e.keyCode); // will tell code for key pressed
    // etc.
timeout(2000, ()=>{
    // remove the keyEvent
    frame.off("keydown", keyEvent);

timeout(4000, ()=>{
    // add the keyEvent back again
    // note - the event must be re-assigned to use again
    // this leads to a tricky bug if not careful!
    keyEvent = frame.on("keydown", keyEvent);
timeout(6000, ()=>{
    // remove the keyEvent again
    // this only works if we re-assigned the latest event to keyEvent
    // which is why we used let rather than const
    frame.off("keydown", keyEvent);

// call this function only once when mousing over the stage
// note: "mousemove" would only trigger if moving over an object on the stage
stage.on("stagemousemove", ()=>{
    pauseAnimate(false); // unpause all animations
}, null, true); // this true means remove the event after calling it once

// a remove() method is available on the event object
const circle = new Circle();
circle.on("mouseover", e=>{
    circle.alpha -= .1;
    if (circle.alpha <= .5) e.remove();

The on() method should NOT be chained. ZIM provides several chainable methods as alternatives:

// TAP
// tap() is like a "click" but the mouse needs to stay in the same area
new Rectangle().center().tap(e=>{
    e.target.rotation += 5;

// all objects that have a "change" event have a change() method
new Slider().center().change(e=>{

// HOV
// hov() can be applied to any DisplayObject
// this is like "mouseover" and "mouseout" events
// most components like a Button already handle this
// alpha if number and color if string
new Circle().alp(.5).center().hov(1); // full alpha on hover

// a press and hold
new Triangle().center().hold(e=>{
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.
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!
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
Dragging in ZIM can be done in several ways: Note: Squiggle() and Blob() objects get their own drag.

Here are tips for drag(). Please see the docs for the others.

// basic drag - will add pointer cursor:
new Circle().center().drag();

// drag object and keep animation of object animating:
// note - the default drag removes animation Tweens
new Circle()
    .animate({props:{scale:2}, rewind:true, loop:true})
    .drag({removeTweens:false}); // good for Sprites too!

// with boundary of stage:
const w = 100;
const h = 100;
const boundary = new Boundary(0,0,stageW-w,stageH-h);
new Rectangle(w,h).center().drag(boundary);

// with boundary for object with center reg:
const r = 50;
const boundary = new Boundary(r,r,stageW-r*2,stageH-r*2);
new Circle(r).center().drag(boundary);

// with boundary for 200 pixels horizontal only (no vertical height):
const boundary = new Boundary(stageW/2-100,stageH/2,200,0);
new Circle().center().drag(boundary);

// drag items in a Container (a Tile is a Container):
const tile = new Tile(new Circle(30,[blue,green,orange]),20,10)
    .drag(); // will drag individual circles

// drag items above without item coming to top:
// note: the default drag brings object to top of its container
    .drag({onTop:false}); // will leave level order same

// drag all items above - not each individual item:
    .drag({all:true}); // will drag whole container

// to stop dragging:

Mouse Events can still be applied while dragging:

const circle = new Circle().center().drag();

circle.on("mousedown", ()=>{
    circle.startX = circle.x;
    circle.startY = circle.y;
circle.on("pressmove", ()=>{
    circle.alpha = 1-Math.abs(circle.x-stageW/2)/(stageW/2);
circle.on("pressup", ()=>{
    // could use circle.noDrag()
    // but that would record the incorrect start position
    // so do not record user press on object
        props:{x:circle.startX, y:circle.startY, alpha:1},
        call:()=>{circle.mouse();} // let user press on object

See ZIM Bits Drag Copy dragging a copy and ZIM Bits Snapping for snapping to objects.

See CodePen Unscramble for dragging and shifting tiles. Etc.

See ZIM NIO and Groovity for dragging on paths.
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, i=>{
    zog(i); // 0-9

// same as ES5:

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:

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

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

const monsters = new Container(); // then fill with monster Bitmaps, etc.
loop(monsters, 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.
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. Tests all the time for when objects are moving on their own

// 2. Use when user move object and the other objects are not moving
object.on("pressmove", e=>{});

// 3. Use when dropping an object in the trash for instance
object.on("pressup", e=>{});

Here is an example of the third:

const ball = new Circle(20).center().drag();
const can = new Rectangle(100, 200).pos(100, 100, RIGHT, BOTTOM);
ball.on("pressup", ()=>{
    // bigger shape hitting points around smaller circle
    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. 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:
let ticker = Ticker.add(()=>{
    if (ball.hitTestRect(rect)) {
// OR
let mousemoveEvent = stage.on("stagemousemove", e=>{
    // see Tip for RETINA as to why we do not use e.stageX and e.stageY
    ball.loc(frame.mouseX, frame.mouseY);
    if (ball.hitTestRect(rect)) {

// 3. Use a check variable (just some logic!):
let hitCheck = false;
ball.on("pressmove", ()=>{
    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:

const circles = new Container().addTo();
loop(20, ()=>{
    // ES6 tip - use let inside loop
    let circle = new Circle(20, green).loc(rand(stageW), rand(stageH), circles);
    circle.collected = false;
const collector = new Rectangle(50, 100).center().drag();
collector.on("pressmove", ()=>{
        if (!circle.collected && collector.hitTestCircle(circle)) {
            curcle.color = black
            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", ()=>{
        if (collector.hitTestCircle(circle)) {
    }, true); // the true makes loop loop in reverse
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.
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", e=>{
    let x = e.stageX/stage.scaleX;
    let y = e.stageY/stage.scaleY;
    // etc.

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

stage.on("stagemousedown", ()=>{
    let x = frame.mouseX; // note mouseX not stageX
    let y = frame.mouseY;
    // etc.
ZIM is built on CreateJS at https://createjs.com and so all CreateJS documentation applies to ZIM. We recommend that you use the ZIM version of CreateJS as it has some helpful updates. See the top of the DOCS for the link.

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 following:


// this gives the CreateJS object
drag(), animate(), hitTestRect(), hitTestCircle(), etc.
center(), centerReg(), pos(), mov(), etc.

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:

const rect = new Rectangle(100,100).center();
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

SETTING BOUNDS - 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.
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
helpful messages to the console as we code.
is just short for JavaScript's

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
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", ()=>{
    zog("clicked"); // runs when object is clicked

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

    // runs at the frame rate - very fast!
    // just check then comment out or delete - can bog performance

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

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

loop(10, 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.
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
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 of ZIM TEN updates):

Positioning and Constants | ThreeJS OrbitControls | Animated Text | Radial Menu | DPad Keyboard Alternative | ZIM 10.5.0 Updates | List Pulldown! | Marquee! | 15 New Features! | hitTestPath | SHIM for Adobe Animate | Retina | Shape Tween Animation | ZIMON | Isometric Game Board | Node Package Manager | Model, View Controller | Intro to TEN Site | Accordion & Tip | Physics | ZIM TEN (10)

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.

Happy   C R E A T I N G   from Dr Abstract and Pragma - at ZIM!