Overview

ProStyle animations are referred to as stories. They are translated from JSON into web content and a timeline. The timeline instructs how the content’s properties are changed over time.

Story

Each story is composed of a canvas, a frame, and one or more flows. Each flow contains one or more pages, and each page contains one or more items.

ProStyle renders the tree of model objects into a tree of HTML and SVG content and a timeline that animates the content’s properties.

Model Objects

Models are the things that exist within the story. They physically exist as web content. They can be configured, styled and positioned. Their properties may be animated with scripts.

Model Description
Canvas The canvas is the drawing surface of the animation. It is mapped to a single div element or the body element of an HTML page. The HTML element might be any rectangular size. For example, a body tag stretches to fit the browser window. There is only one canvas.
Frame The frame is centered within and stretches to fit the canvas, minus any padding. However, unlike the canvas, the frame always maintains a configured aspect ratio. There is only one frame.
Flows Flows control page-to-page animation, such as page stacks, carousels, etc. Each flow contains one or more pages.
Pages Pages contain the item content. The timeline navigates from page to page. Pages are analogous to slides in old-school presentation software.
Items Items are the core visuals, such as text, images, and charts.

Structure

All story documents follow the same general structure. See if you can recognize the pattern in the following example. Just about everything is optional.

If the following looks like gibberish, don't fret. it’s only JSON, which you can learn about here.
{
  canvas: {
    setup: {...},
    init: {..}
  },
  frame: {
    setup: {...},
    init: {...}
  },
  flows: [
    {
      flowType: "...",
      setup: {...},
      pages: [
        {
          init: {...},
          scripts: [
            {
              scriptType: "...",
              actions: [{...}, {...}]
            },
            {...}
          ],
          canvasScripts: [...],
          frameScripts: [...],
          items: [
            {
              itemType:"...",
              init: {...},
              scripts: [...]
            },
            {...}
          ]
        },
        {...}
      ],
    }
  ]
}

The above might look a bit complicated. If you study it for a moment, though, you’ll see a pattern. Each model object can have setup, properties, or both. Properties are initialized with init.

Pages and items may have scripts. Each script has actions such as to animate property changes. The canvas and frame may also have scripts, but they are triggered in conjunction with a page using canvasScripts and frameScripts. For example, you might decide to change the canvas background when a certain page is displayed.

Shortcuts

To keep story documents concise, ProStyle supports shortcuts. There are three kinds.

  1. Flows, Pages and Items
  2. Scripts and Actions
  3. Setup

Flows, Pages and Items

Since a story may have more than one flow, the root of the document has a flows entry that accepts a list using [ ] brackets. Each entry in the list is a flow object, with { } brackets.

{
  flows: [
    { pages: [{...}, {...}] },
    { pages: [{...}, {...}] }
  ]
}

However, if the story has only one flow, the document can omit the flows entry and use a flow entry instead.

{
  flow: { pages: [{...}, {...}] }
}

That’s better, but if there is only one flow and it is the default simple flow, the document can just have page or pages, depending upon the number of pages.

{
  pages: [{items:[...]}, {items:[...]}]
}
{
  page: {items:[...]}
}

Furthermore, if there is only one page, and that page doesn’t override the defaults (no property init or scripts), the document can have just the child items or item, depending upon the number of items.

{
  items: [{...}, {...}]
}
{
  item: {...}
}

When parsing a story, ProStyle searches for and uses, in order, flows, flow, pages, page, items, item. Only one will be used. Once one is found, others are ignored.

Scripts and Actions

Scripts and actions may be shortcutted like flows, pages, and items. If there are multiple scripts, then a scripts entry must be used. Otherwise, just use script. If the one script is the default scriptType (step) then just use actions or action depending upon the count of actions.

ProStyle searches for and uses, in order, scripts, script, actions, action. Only one will be used. Once one is found, others are ignored.

Note that some model objects have multiple sets of properties. For example, the text item has word properties. When shortcutting, prefix the name of the property set. e.g. wordScript, wordActions, wordAction, etc.

Setup

All one-time configuration of a model object is defined inside a setup entry. However, if you wish, you can omit this extra level. If configuration is not found in a setup entry, it looks one level up on the model object itself.

Either of these is valid for a text item.

{
  setup: { text: "animate!" }
}
{
  text: "animate!"
}

JSON

JavaScript Object Notation is a simple text file format. It uses named values. Each value may be one of 5 basic types of information; object, array, text, number or true/false.

ProStyle uses a lenient form of JSON called JSON5.
JSON supports others types of values, but these 5 are what you’ll use with ProStyle.

Objects

An object is a container of named values. Each object is enclosed in curly { } brackets containing zero or more named values. Each named value is separated by a comma. Objects can have named child objects.

{
  town: "boston",
  zipCode: 2112,
  child: { ... }
}

Primitives

There are three primitive value types.

  • Numbers can be positive or negative, with or without a decimal point.
    • They should not have formatting, such as commas.
  • Strings are lines of text wrapped in quotes.
  • Booleans are either true or false.
{
  year: 2015,
  title: "ProStyle",
  awesome: true
}

Arrays

Arrays are lists of values. They are enclosed in square [ ] brackets. Listed items are separated by a comma. Arrays may hold any of the types, including child arrays.

{
  numbers: [1,2,3],
  strings: ["a", "b", "c"],
  booleans: [true, false, true],
  objects: [{number: 1}, {string:"a"}, {}],
  arrays: [[0,0], [100,100]],
  mixed: [652, "banana", [true, false]]
}

Resources


Setup vs. Properties

Setup and properties are two distinct ways that model objects are configured. The difference is subtle, but important.

Setup

Setup defines one-time configuration, which is core to how the model object works. Setup values are immutable. That means that they are set once and cannot be changed. ProStyle uses the setup to render and optimize the object. For instance, setup values might determine what HTML or SVG content to use. Setup values are defined in a setup entry.

{
  itemType: "text",
  setup: { text: "ProStyle!" }
}

Properties

Unlike setup, properties can be changed. They are initialized in an init entry and can be changed in a script.

{
  itemType: "text",
  setup: { text: "ProStyle!" },
  init: { opacity: 50 }.
  action: { delay: 5, opacity: 0 }
}

Animation

Animation is the changing of properties over time using scripts. Multiple scripts may execute concurrently within a step, and the steps are sequenced into a timeline.

Timeline

After reading the JSON, ProStyle inserts the required HTML and SVG into the web page, and sequences the scripts into a timeline. Think of the timeline like a movie player. It is linear. The player will play from beginning to end, and the playhead can be seeked to any time as needed.

Scripts

A script is a sequence of one or more actions. A script’s actions are executed in order, one after the other. Once an action completes, the next one begins. Scripts within a step run in parallel, but actions within a script run in series.

The duration of a script is the sum of its action’s durations. Extending the duration of an action pushes out the start of any remaining actions within that script.

The duration of a step is the duration of its longest script.

The combination of serial steps of parallel scripts of serial actions makes ProStyle very powerful. It’s easy to craft simple animations, yet flexible enough for complex interactions.

Set-Properties Action

Actions do things, such as set property values. Currently, ProStyle only supports one type of action: set properties. So, the default actionType entry is "properties". Future versions of ProStyle might support other types of actions.

  • An action may have a delay property which describes how long to wait until the changes begin.
  • An action may have an animation property which describes how to change from old property values to new ones.

The duration of the action is the sum of the delay and animation values. If properties are set without a delay or animation then they will change instantly once the script executes the action, and the action will have no duration.

If two scripts attempt to change the same property value of the same model object at the same time, the second one will win. The first one will be cancelled.

Events

Events trigger the start of scripts. Events are also referred to as script types. There is currently only one kind; when a step has started. Other script types are under consideration for future versions. e.g. mouse and touch interaction.

Scripts have a scriptType parameter, which can be “step1“, “step2“, “step3“, …

  • If the scriptType is omitted, the default value is “step1“
  • A value of “step” is an alias for “step1“

Steps

The timeline has markers called steps. Multiple scripts can be processed simultaneously starting at a step. The next step does not start until all scripts in the prior step complete. The total duration of a step is the duration of the longest script it contains. The steps belong to a page. Every page contains one or more steps.

ProStyle generates a timeline by parsing all of the scripts on each page, which includes the page’s scripts, any canvasScripts or frameScripts, and all of the scripts for the page’s items. Each script is associated with a step. The timeline plays each step in order, moving from page to page, as the last step of each page completes.

Each step is associated with a single page, and each page is a member of a single flow. Therefore, any given playhead position in the timeline is associated with one flow, one page, and one step.

Eases

Eases are used to control how quickly or slowly a change occurs relative to the constant pace of time. They map any time within the duration of the animation to the completion percentage of the property change. Easing can be used to apply an effect, like bouncing or elasticity.

An ease is composed of a timing function, a direction and a strength.

Timing Functions

Function Description
"back" The property value goes beyond the target value, slows down, and then returns and rests at the target value. It is like a one-pass elastic ease.
"bounce" The property value reaches the target value quickly, bounces back toward the start value, over and over, diminishing in strength each iteration.
"circle" A curved function that looks like a circle when plotted. It is only slightly different than sine.
"curve" a simple quadratic curve where the activity starts quickly and slows as the target value approaches.
"elastic" Similar to bounce except the diminishing bounces alternate between each side of the target value.
"expo" a simple reverse exponential curve where the activity starts quickly and slows as the target value approaches.
"linear" The property moves from starting value to target value at a constant rate.
"sine" A curved function based on the sine trigonometric function. It is only slightly different than circle.
"slowmo" The property quickly progresses and then slowly progresses and then quickly progresses to the target value.
"slowmoback" Similar to slowmo except the slow part plays backward.
"stepped" The distance between the starting and target values is segmented into 3, 6, 12 or 24 steps, depending upon the strength.
"stop" The animation starts quickly, decelerates to a stop in the middle, and then accelerates to the target value.
"stopandreturn" Similar to stop, but the stop point is the target value and the animation ends back at the start value.

Direction

Direction Description
"out" The effect of a timing function happens at the target value side. This is the default.
"in" The effect of a timing function happens at the starting value side.
"inout" The effect happens on both sides.

Strength

The impact of each strength value is particular to each timing function. For example, it effects the number of steps with "stepped", the length of the slow section of "slowmo", the iterations with "elastic", etc.

Strength Description
"less" The effect is diminished.
"normal" The default configuration, usually the best.
"more" The effect is stronger.
"extra" The effect is very strong.

Staggering

When there are multiple targets, like bars in a chart or characters in text, each can be staggered by applying a delay using the stagger value of the animation property.


Alignment

Unlike traditional web graphics, ProStyle is designed to work with center alignment. Add an item to a page and it will be automatically centered, regardless of its current or future size. Furthermore, positioning is relative from the center, as a percentage of the container’s dimensions. This greatly simplifies layout. Because the frame maintains its aspect ratio, the animation will look the same on any screen of any size.

Anchor

With center alignment, the center of the item is positioned on the center of its container. The reference point on the item is called the anchor. Each item has an anchor property and a position property. Both default to [0,0], which is the center of the item. The position property defines where the item is placed, relative to the container’s center. The anchor defines what point on the item will be directly on the position location. Anchors make it easy to align objects of different sizes.

Transform Origin

The transform origin, like the anchor, is a reference point on the item (unless expanded). It defines the point that transforms are relative to. For instance, to rotate an item around its top left corner, the transform origin would be set to [-50,-50]. By default, items rotate around their center because the transform origin is initially set to [0,0].

By default, the x and y values of the transform origin are percentages of the item’s dimensions. However, if the expand value is set to true, the numbers will be considered a percentage of the container’s dimensions, usually the page.


Color

ProStyle supports the standard web formats for describing color.

Named Colors

The simplest option is to use a color by name. All standard browsers support a large set of HTML and X11 color names. Any of these names may be used in a property that expects a color. They are not case sensitive.

RGB

Another common way to describe a color is to combine the three primary colors; red, green and blue. Display devices use an additive color model so adding these primary colors results in lighter colors, topping out at white. Reducing the amount of primary color results in darker colors, approaching black. Each value has a decimal range of 0-255. A red value of 0 means no red. A red value of 255 means as much red as possible. Any combination of these three colors can be written using the rgb() syntax. rgb(0,0,0) equals black. rgb(255,255,255) equals white. rgb(255,255,0) equals yellow, and so on.

There is also a version of rgb that supports semi-transparency. The forth parameter of rgba(255,255,0,0.5) is a number between 0 and 1, where 0 is completely transparent and 1 is completely opaque.

Hex

It is very common for web colors to be described with hexadecimal numbers. Instead of each digit having 10 values (0 to 9), each digit has 16 values (0123456789ABCDEF). Color values in hexadecimal range from 00 to FF, which is 256 distinct values just like 0 to 255 is in decimal. Hex colors are prefixed with a hash character to distinguish them.

All of these represent the same solid red color.

color: "red"
color: "rgb(255,0,0)"
color: "rgba(255,0,0,1)"
color: "#FF0000"
color: "#F00"

Notice the last one has only one hex value per primary color. This is a short form which uses shorter strings in return for less granularity.

HSL and Alpha

A different way to describe colors is with hue, saturation, and lightness. Hue is the 360 degree color wheel value representing the rainbow of colors. Saturation describes how vivid the color is. 100% is as vivid as possible. Lower numbers make the color grayer (washed out). A lightness higher than 50% approaches white, and a lightness lower than 50% approaches black.

Optionally, an alpha value between 0 and 1 may be used to make the color semi-transparent. hsl(0,100%,50%) is red. hsla(120,100%,50%,0.5) is semi-transparent green.


3D

ProStyle makes it simple to place and animate objects in three dimensions. It’s important to note, though, that the objects themselves have no depth. Imagine a piece of paper held out in front of you. It has width and height, but no depth. Of course paper does have a small amount of depth, but imagine it didn’t. If it was turned 90 degrees on its side, you would no longer be able to see it. With ProStyle, two dimensional objects can be positioned anywhere in 3D space, just as our piece of paper can be moved around the room.

Since the device’s screen is also two dimensional, modern browsers have built-in support to emulate a third dimension by using perspective, which ProStyle leverages when rendering. ProStyle configures a vanishing point in the center of the screen. The dimensions of the frame provide the horizontal and vertical extents of the view space. The depth, or length of the Z axis, is calculated based on the X and Y axes, using Euclidean geometry.

Example

edit & play
{
  classes: {
      text3d: {
        position: {z:3},
        font: 30,
        color: "#456",
        textShadow: [0.5,0.5,2,"rgba(0,0,0,0.5)"]
      }
  },
  item: {
      itemType: "layer",
      init: {
        size: [50,40],
        bg: "rgba(255,255,127,0.7)",
        corners: true,
        shadow: [0.5,0.5,2,"rgba(0,0,0,0.5)"]
      },
      scripts: [
          { action: {delay:1, anim:10, rot:{x:540}}},
          { action: {delay:0.5, anim:[12,"bounce"], rot:{y:540}}},
          { action: {anim:11, rot:{z:-540}}}
      ],
      items: [{
        text:"In 3D!",
        init: {class:"text3d", pos:{z:4}}
      },
      {
        text:"In 3D!",
        init: {class:"text3d", pos:{z:-4}}
      }]
  }
}

Placement

Placement is a term used to describe where an object is in 3D space. When this documentation refers to placement, or how an object is placed, it means the combination of the following four properties.

The scale and opacity properties do not really influence where an object is placed, but they are included in this definition nevertheless. It is not always easy to visually distinguish whether an object is moved along the z axis (three d) or simply scaled larger. Opacity is included because the transparency level indicates what can be seen behind it.

Animating only placement properties may trigger hardware acceleration on devices that support it, for fast, smooth animation.

Performance

ProStyle generates web content and scripts that leverage hardware acceleration whenever possible. Hardware acceleration happens when the animation uses certain approaches that allow the video card processors (GPU) to do calculations, and use algorithms that are embedded in hardware, as opposed to programs in random access memory. They can be significantly faster than using standard CPU processors. Video processors are designed to maximize parallel execution.

The way in which a story is written will impact whether parts of the animation may be processed by the video hardware. A general understanding of compositing will help you write more efficient animations.

Compositing

Individual content is processed by the GPU separately and then combined. Think of it like layers in Photoshop. Each layer represents a two-deminsional array of pixels. The browser will rasterize the content (draw it as pixels) into each layer. The size, in pixels, is defined by the content (e.g. font size). The act of drawing the pixels is not hardware accelerated because the software in the CPU must build the bitmap that will later be processed by the GPU.

Once a layer is created, it can be manipulated very quickly using hardware-based routines. The layer can be scaled, rotated, made semi transparent, and so forth. Animating properties that force the layer to be redrawn will be slower than those that manipulate an existing layer. If an animation changes only one or more of the placement properties, it may likely be hardware accelerated by the GPU.

Size vs. Scale

The scale property stretches content vertically or horizontally. The stretching is performed after the content has been rasterized to pixels. So, scaling larger will make the content look pixelated. To avoid pixelation, the content may be rendered larger and initially scaled much smaller. The animation can then scale up to the natural dimensions. However, there is a tradeoff. This approach will render a larger bitmap layer and use more GPU memory.

edit & play
{
  item:  {
    text:"font",
    init: {
      pos:[-50,-50], anchor:[-50,-50],
      origin:[-50,-50], color:"#094766",
      font:300, scale:10
    },
    action: {
      anim:{ dur:5, rep:1, yoyo:true },
      scale:100
    }
  }
}

Stacks

undocumented