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.
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.
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. |
All story documents follow the same general structure. See if you can recognize the pattern in the following example. Just about everything is optional.
{
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.
To keep story documents concise, ProStyle supports shortcuts. There are three kinds.
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 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.
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!"
}
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.
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: { ... }
}
There are three primitive value types.
{
year: 2015,
title: "ProStyle",
awesome: true
}
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]]
}
Setup and properties are two distinct ways that model objects are configured. The difference is subtle, but important.
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!" }
}
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 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.
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.
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.
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.
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 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“, …
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 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.
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 | 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. |
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. |
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.
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.
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.
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.
ProStyle supports the standard web formats for describing color.
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.
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.
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.
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.
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.
{
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 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.
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.
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.
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.
{
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
}
}
}
undocumented