Documentation index

About the Burst Engine

Why Burst?

I created Burst because I wanted a quicker, easier way of building complex animations on the HTML Canvas for both UI elements and JavaScript games. I had been experimenting with Processing.js ever since it's timely release in summer 2008. While I began creating my own UI elements in PJS, I found the process to be tedious and began combining my methods into a script I could include when PJS loaded.

Having been a freelance web designer/developer for some years, I had crossed paths with Flash many times. Personally... I never liked Flash. A) It was a closed system in a world built explicitly on open systems. B) I found it's workflow unessesarily complicated. C) People started making whole web-sites with it, which I would have to download on a 28k modem. ( No offense to Flash developers, as some of you guys clearly do some awesome things with Flash but it was just never an HTML kid's cup of tea. )

So in winter 2008 I set about building Burst to combine the vector functions of Flash with the timeline flow of AfterEffects and the codability of jQuery. The Burst Engine is about simplicity, speed & flexibility.

For a guy with little knowledge of OO, and advanced JavaScript animation techniques it has been a steeply curved journey; but as time moves forward I continue to find The Burst Engine to be extremely useful when creating flashy JS applications for the web. And so: at the point where I have Burst running with Processing.js, native Processing and bare-bones JavaScript, I have decided to switch my main focus to furthering Burst's development and promoting it as a userful tool for the web.

Goals

Burst has been created with specific goals in mind. These are:

  1. <UI> A system to quickly create UI elements such as dials, curved sliders etc.
  2. Flash A JavaScript alternative to Flash
  3. Games An animation engine to assist JavaScript game development
  4. VJing A frame-workto drive a Comet based VJing application for clubs.

PJS, PDE & JS

Burst comes in three delicious flavours:

  1. PJS: A Processing.js version for users that want to use Burst commands in their Processing.js script.
  2. PDE: A Native Processing version for people who want to create desk-top applications or Java web-applets that use the Burst engine.
  3. JS: A light weight JavaScript version of Burst. Burst.js is my primary focus.

Features

Name:Description:Code:Demo:Reference:
Command chainingCommand chaning allows sripters to access Burst objects and commands using in an easy-to-read format.
Burst.timeline("party", 0, 25, .5, false)
  .shape("balloon", "balloon.svg", "outline")
    .track("top")
      .key(1, 100)
      .key(25, -20);
Command ChainingDetails
Callbacks A callback is a peice of code, or function that excecutes when another command has completed.
Burst.play("myTimeline", function(){ alert("finished");} );
SVG ImportBurst can import SVG files to the Canvas.
HEX AlphaBurst uses HEX Alpha to parse colors.
shape("myShape").fill = "ff0000ff";
.OFF ShapesBurst can read .OFF objects exported from Blender 3D. These shapes are interpreted as 2D outlines, so you will need to order the vertexes as such when creating your objects.
.OBJ ShapesBurst can also read .OBJ objects exported from Blender 3D. These shapes are interpreted as Quad and Triangle vertexes making filled faces or wireframe outlines. These vertices do not need to be ordered in any way.

Features in Development

Name:Description:
Recursive object cloningAllowing the scripter to clone a timeline and all it's objects with new names.
keyframe overwitesAt the moment keyframes do not have unique IDs so creating two property keys in the same frame will cause the second key to be the real value. They correct behaviour would be for the previous key to be overw-written.
Z-IndexingZ-Indexing has not yet been implamented. This will apply to timelines and shapes.
Effect ModulesEffect modules will transform the shape data of an object by given paramters. This could be used to create animat-able drop-shadows, glows, wraps/distortions or anything else that can be envisioned.
Shape tweeningSimilar tweening functions to Flash. This will allow the morphing of shape objects or the keying of shape animations. EG: you could create 3 SVG shapes of a dove flying and then tween between (smooth or step interpolation), to create an animated shape. Should be great for similfying game creation.
TransitionsAllows for transitioning between timelines. IE: cross-fade, circular-wipe etc.
Burst IDEBurst will have an AJAX based IDE to assist in the animation process. The IDE will also allow the editing of shapes and should be intuitive enough for children to use. The IDE will also allow the exporting of a script to an HTML document and will support live-scripting in a similar manor to ActionScript.
Physics engineBurst will have a basic 2D Newtonian-based physics engine supporting rigid masses and support object collision of convex & concave shapes.
Particle engineBurst will also have a particle engine fo creating smoke, sparks, bubbles etc.
Ray-castingBurst will support convex & concave ray-casting, allowing for the interaction and collision between shapes and UID's such as a mouse, adding events to shapes such as: onClick and drag.
True-type FontsBurst will support true-type font rendering. Strings will be parsed to SVG shapes until such point as TTFs can be supported natively by the Canvas.
3D RenderingBasic 3D may be supported in future versions of Burst. Complexity being added as Browsers begin support OpenGL hardware in actual releases.
Burst.js IE supportMaybe one day, who knows?

Userful Links

  1. Hyper-metrix.com Home of Burst
  2. GitHub Master Burst's Public Repository
  3. Burst IRC Channel A place to for quick answers to good questions.
  4. Mozilla's Canvas Tutorial Very useful Canvas method documentation
  5. SVG Specification W3C's SVG Outline
  6. Stroke-DashArray A method for Stroke-Dashing lines in the canvas.
  7. CAKE An alternative JavaScript animation engine for Canvas.
  8. InkScape SVG Tests
  9. Tiny SVG

Reference

.timeline()

The timeline() command references a new or existing timeline object inside your Burst animation. A timeline can be thought of as a container for objects that are animated over time. A timeline can be played at different speeds or reversed. When a timeline moves, all it's children move. When a timeline has effects it's children are inherit (or not) these effects. A timeline can contain other timelines. Each timeline can act like a single object, with rotation, scale, transparency etc.

Object initilization:

Burst.timeline("myTimeline", start, length, speed, looping);

Property access:

Burst.timeline("myTimeline").fill = "ff0000ff";

Property animation:

Burst.timeline("myTimeline")
  .track("fill")
    .key(0, "ff0000ff")
    .key(100, "00ff00ff");

Possible children:

  1. timeline();
  2. shape();
  3. track();
  4. fx();

Possible properties:

Name:Init./default Value:
namevalue passed at init.
widthCanvas width
heightCanvas height
type
"timeline"
frameOffset0
lastFramevalue passed at init.
playSpeedvalue pass at init.
loopvalue passed at init
pausedfalse
frame0
callbackfiredfalse
randomCount0
playModeforward
scl1.0
sclX1.0
sclY1.0
left0
top0
rot0
strokeW0
strokeHex, strokeRGBA[]"00000000", [0, 0, 0, 0]
strokeR, strokeG, strokeB, strokeA0, 0, 0, 0
fillHex, fiilRGBA[]"00000000", [0, 0, 0, 0]
fillR, fillG, fillB, fillA0, 0, 0, 0
opac0.0
centerXCanvas middle
centerYCanvas middle
isParentlink to object's parent
timelines[]array[]
shapes[]array[]
tracks[]array[]
effects[]array[]

.shape()

A shape is an object containing vertexes or points to be rendered onto the Canvas. Shapes can be drawn with curves, straight lines and even raw vertexes exported from Blender3D or imported as SVGs. Shapes can include other shapes. A shape can have types such as "subpath" which leaves an open path, very userful for creating subtractive shapes (shapes with holes) using the non-zero or 'opposite winding' rule.

Object initilization:

Burst.timeline("myTimeline").shape("name", "url", drawmode, left, top, scale, rotation, stoke width, "stroke color", "fill color", zIndex);

Property access:

Burst.timeline("myTimeline").shape("myShape").fill = "ff0000ff";

Property animation:

Burst.timeline("myTimeline")
  .shape("myShape")
  .track("fill")
    .key(0, "ff0000ff")
    .key(100, "00ff00ff");

Possible children:

  1. shape();
  2. track();
  3. fx();

Possible properties:

Name:Default Value:
namevalue passed at init.
urlurl to AJAX shape data from
obj[]actual shape data, can be passed as array if you don't want to use AJAX
widthCanvas width
heightCanvas height
modeDrawmode: Shape, subpath, verts, SVG etc. Value passed at init.
winding1 (-1 reverses draw-order)
type
"shape"
frameOffset0
lastFramevalue passed at init.
playSpeedvalue pass at init.
loopvalue passed at init
pausedfalse
frame0
callbackfiredfalse
randomCount0
playModeforward
scl1.0
sclX1.0
sclY1.0
left0
topmiddle of cavas
rot0
strokeW0
strokeHex, strokeRGBA[]"00000000", [0, 0, 0, 0]
strokeR, strokeG, strokeB, strokeA0, 0, 0, 0
fillHex, fiilRGBA[]"00000000", [0, 0, 0, 0]
fillR, fillG, fillB, fillA0, 0, 0, 0
opac0.0
centerXCanvas middle
centerYCanvas middle
isParentlink to object's parent
shapes[]array[]
tracks[]array[]
effects[]array[]

.track()

Tracks or 'property-tracks' are small timeline-like objects containing key frames. Each track is linked to a property of it's parent EG: 'scale'. The value of the key frames adjust the relevant property as the timeline is played.

Object initilization:

Burst.timeline("myTimeline").shape("myShapen").track("track-property");

Property access:

Burst.timeline("myTimeline").shape("myShape").isParent = Burst.timeline("myTimeline").shape("myOTHERShape");

Possible children:

  1. key();

Possible properties:

Name:Default Value:
namevalue passed at init.
propertyValue passed at init.
keys[]array[]
isParentparent node in chain

.key()

A key or 'key-frame' contains animation properties for an object at a given frame. Think of keys as markers that the animation engine uses to interpret what the Canvas should look like at any given moment. When the current frame of a timeline matches the key's frame property, the value from the key() is dumped directly into the object's property variable. All frames between key()'s are interpreted based on the speed of the timeline and the ease-type being affected.

Object initilization:

Burst.timeline("myTimeline").shape("myShapen").track("track").key(frame, value, easing);

Property access:

N/A

Possible children:

none

Possible properties:

Name:Default Value:
frameValue passed at init.
propertyValue passed at init.
easingValue passed at init.

.chain()

The .chain() command is a method of the Burst Master Controller. When calling Burst.chain("timeline1;timeline2");, Burst will load these timelines into it's buffer ready to be played one after the other. You may optionaly specify a callback routine.

Burst.chain("timeline1;timeline2", function(){} );

.play()

The .play() command is a method of the Burst Master Controller. Play begins or continues playing the timelines loaded to the buffer.

Burst.play();

.pause()

The .pause() command is a method of the Burst Master Controller. This will pause the animation at the current frame until .play() is called again.

Burst.pause();

.angleTo()

The .angleTo() command returns the angle from the current object to the object passed. The angle is returned in degrees, 0 always being North. Remember to take layer rotations into account when building complex scenes.

var cursor  = Burst.timeline("myTimeline").object("customCursor");
var compass = Burst.timeline("myTimeline").object("compassArrow");

// Point the compass at the cursor...
compass.rot = compass.angleTo(cursor);

Example: Mouse Tricks

.always()

The .always() command is a callback function that runs at the beggining of every frame before things are drawn to the canvas.

annoy=function(){
  alert("Wow these alerts are really annoying!");
}
Burst.always(annoy); 

The .always() function can be applied to single timelines also:

annoy=function(){
  alert("Wow these alerts are really annoying!");
}
Burst.timeline("alertsSuck").always(annoy);

Command Chaining

   
Burst.timeline("party", 0, 25, .5, false)
  .shape("balloon", "balloon.svg", "outline")
    .track("top")
      .key(1, 100)
      .key(25, -20);   

The above five lines of code create a timeline, add a shape, add a property track to the shape, and then add keyframes to the track. Can you read what it does? It creates a timeline called 'party', adds a shape called 'balloon', adds keyframes to the "top" property of the balloon, making it rise off the canvas in 25 frames.

(But it will really take 50 frames because the playback speed of this timeline is set to ".5" Negative values will play in reverse. )

This shorthand "chaining" way of writting code is great for several reasons.

  1. It is quick to write.
  2. It is easy to read.
  3. It saves download Kbs.

I wrote Burst's chaining method a differently from jQuery because it's Objects do not relate to any kind of DOM tree. In jQuery one would climb up and down the tree something like this:

$(myObject).children(childObject).value(setValue).parent().children(childObject2).value(setValue2);
   ...or...
$(myObject).children(childObject).value(setValue).next(childObject2).value(setValue2);

This is great for DOM manipulation, but too bulky for a simple key framing system. In Burst you can call a new parent at any time and Burst will return the matching object for manipulation. Watch this:

Burst.timeline("party", 0, 25, .5, false)
  .shape("balloon", "balloon.svg")
  .shape("cake", "cake.svg")
    .track("left")
      .key(1, 50)
      .key(25, 100)
  .shape("balloon")
    .track("top")
      .key(1, 100)
      .key(25, -20);            

Even though the shape ballon was already called, and the chain's level was at the "key-frame" editing point... calling .shape("balloon") will cause Burst to return the previous balloon object without the coder having to climb up and down the tree. This becomes really useful if you wish to add 30 objects to one timeline .shape(1).shape(2).shape(3) at different X,Y points and then use the "top", "left" property track of the timeline to control the position of all the shapes at once.

For clarrification, the above examples can be written in one string like so:

Burst.timeline("party", 0, 25, .5, false).shape("balloon", "balloon.svg").shape("cake", "cake.svg").track("left").key(1, 50).key(25, 100).shape("balloon").track("top").key(1, 100).key(25, -20);

Parsing XML in Chrome/Safari with Javascript

One interesting thing I noticed when trying to parse SVG documents in Chrome/Safari with Javascript was that the document is returned without the DocType information. For example.... when XMLHttpRequest to load an SVG's XML in FireFox, the following (and correct) is returned...

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg ...

But in the evil Safari/Chrome, DocType is not returned...

<svg ...

This means that Safari / Chrome's xmlDoc is actually the <svg> tag. And FireFox's xmlDoc is actually the whole XML document. Go Firefox! This was extremely annoying as I spent a lot of time wondering why my .getAttribute("svg")[0] returned nothing in Safari/Chrome. It was returning a NodeList, with no nodes! Fortunately the answer turned out to be very simple. All I needed to do was call .getAttribute("svg")[0] in Firefox and just use the xmlDoc in Safari / Chrome.

FireFox's Global Alpha Bug

At the time of writing this (2009 March 11th), FireFox contains a bug re: the Canvas' globalAlpha method. In FireFox, global alpha gets ignored when rendering gradients. GlobalAlpha works correctly in Safari, Chrome and Opera. ( Global Alpha Gradient Testcase ) I filed this bug with Mozilla: Bug 482751. To which I am told that it is fixed in the latest nightly, which I downloaded and apparently that's not true, at least in the WIN32 version.

2009 March 27 - The Global Alpha is fixed in the latest nightly.

Safari's Gradient-Stroke Bug

Unfortunately Safari seems incapable of applying a gradient to a strokeStyle (2009 March 11th). FireFox, Chome and Opera can do this just fine. Gradient-Stroke Test Case. Bug filled with Apple Developer Connection (Follow-Up: 69318849).

FireFox's ArcTo Bug

I have been tracking FireFox's Canvas arcTo bug (BUG: 471281) for a few weeks now. It looks like it is getting fixed, but it's still not working in the nightly builds (as of 2009.Mar.27). This is a super-annoying bug as it means you can draw circles in Inkscape and export them to Burst. There are some arcTo() tests here: Philip's HTML5 ArcTo Test, Hixie's context Arc Test & Lazy Illuminati's ArcTo Test. It's worth running these in different browsers to see just how much the ArcTo command fails.