General Principles

Studio

General Principles

Before embarking on this page it's recommended that you have a working knowledge of TypeScript, or have read the TypeScript Primer.

The Zappar platform makes it possible to build dynamic and interactive experiences using TypeScript. Most things that are possible within the editor are also possible from TypeScript.

This page introduces how to use TypeScript within the Zappar platform.

Accessing Existing Nodes

Things that exist in the "Hierarchy" of your project (we call them "nodes") are accessible in your TypeScript scripts using the symbol.nodes variable:

var myroot = symbol.nodes.root;

ZapWorks Studio will automatically create a variable declaration using symbol.nodes when you drag a node from the Hierarchy into an script and select 'Insert a local variable'.

Once you have a reference to a node you may call functions on it in order to read or change its state:

// Change myroot's position to [1, 0, 0]
myroot.position([1, 0, 0]);

// Store the position in a variable
var myposition = myroot.position();

// myposition now contains the value [1,0,0]

Most of a node's properties have a "getter" e.g. position(), which returns the value for that property but takes no arguments; and a "setter" e.g. position(...) which changes the property to the value of the supplied argument.

In general the "setter" function returns the node it's being called on. This makes it possible to chain up "setter" calls like this:

myroot.position([0, 1, 0]).color([1, 0, 0, 1]);

// myroot is now at [0, 1, 0] and is red

All properties that you see in the "Properties" view of the editor are accessible using getters and setters in this way. Complete documentation of all of the functions available on nodes is available in the reference area.

Constructing Nodes

In addition to accessing nodes that are already created in the "Hierarchy" area of your project, it's possible to create new nodes.

// Construct a new object of type "plane.aro"
var newobject = Z.Object();
newobject.type("plane.aro");

// Add the object in to our root node
var myroot = symbol.nodes.root;
myroot.push(newobject);

Notice that we had to add the Z.Object that we created to the root node of our symbol in order for it to be displayed.

In Zappar, all functions that construct new nodes start with an uppercase first letter, e.g. Z.Object(), Z.Group().

Events

We can set handler functions on events for many of the node types in the Zappar platform. Event handlers are registered with the on(...) function, like this:

var myobject = symbol.nodes.myobject;
myobject.on("pointerdown", function(evt) {
  myobject.color([1, 0, 0]);
});

Handler functions will be called every time the event condition occurs, in this example when the object is clicked. There may be circumstances where you want to cancel your event callback. The off(...) function is provided for this purpose:

var myobject = symbol.nodes.myobject;

// Declare a function that we'll use when the user's finger moves across the object
var myMoveFunction = function(evt) {
  console.log(evt.localPosition);
};

// Only start listening for the move event when the use has clicked down on the object
myobject.on("pointerdown", function(evt) {
  myobject.on("pointermove", myMoveFunction);
});

// When the user's finger is no longer over the object remove the move event
myobject.on("pointerleave", function(evt) {
  myobject.off("pointermove", myMoveFunction);
})

It's often the case that you want a function to be called only one time when an event occurs. The one(...) function is provided for convenience in this case:

var myobject = symbol.nodes.myobject;

myobject.on("pointerdown", function() {
  console.log("Pointer down!");

  myobject.one("pointerup", function() {
    console.log("Pointer up!");
  });
});

Running code at different times

The code inside an event handler function will be instantly evaluated when that function is called and the code inside a script is evaluated when the project starts. There are a number of method for executing code and an arbitrary time in the future. This makes it possible to animate your experiences.

Z.after(ms, func)

Use this method to schedule a function to be called after a specified number of milliseconds.

Z.after(2000, function() {
  console.log("Two seconds have elapsed!");
});

Z.every(ms, func)

This method will execute the function repeatedly, at the specified interval.

Z.every(1000, function() {
  console.log("Tick!");
});

By maintaining a variable containing your function it's possible to cancel the repetition.

var myTicker = function() {
  console.log("Tick");  
};

Z.every(1000, myTicker);

// Somewhere else
Z.everyOff(myTicker);

Z.on("frame", (ms: number) => void)

Setting a function to the "frame" event of the Z variable allows you to execute code every frame that's drawn on-screen. It's highly recommended that you avoid this if you can as it can have significant perrformance implications.

Z.on("frame", function() {
  console.log("Frame!");
});

The event handler function is passed a single argument; the time of the current frame, in milliseconds, since the experience first initialised.

Z.on("frame", function(time) {
  var currentTime = time;
});
Open in new window