AjaxPatterns
This is the original book draft version for the One-Second Motion Ajax pattern, offered for historical purposes and as an anti-spam measure.
You're probably better off visiting the Live Wiki Version for One-Second Motion instead, where you can make changes and see what others have written.

One-Second Motion

Copy, Displace, Duplicate, Jump, Leap, Move, Movement, Motion, Rearrange, Transfer

Goal Story

Bill is adding a new monthly bank order. The existing orders are shown in the usual way: as a table with one row per order, sorted by cost. Once he's verified the new order form, it morphs to become a table row, then slowly drifts down the table. It soon reaches its rightful place in the sorted table - ordered by amount - and comes to rest after bouncing up and down a little due to reverberation.

Problem

How can you communicate that an element is shifting from one position to another?

Forces

  • An element's location is important as it can provide cues about its prominence and relationship to other elements.

  • An element sometimes needs to move from one place to another.

  • Similarly, a new element sometimes needs to be created, and then move from where it was created to another location.

  • When an element changes position, the user often needs to know about it.

Solution

Incrementally move an element from one location to another, or temporarily move it, to communicate an event has occurred. In most cases, the motion of the element involves a permanent change to its position. It can also be used to show a temporary displacement or gesture, such as a vibration effect.

There are several benefits of showing the motion explicitly:

  • The motion and the extended transition time make it likely the user will notice something's happened.

  • The motion will highlight where the element is moving to (it won't get lost on the page).

  • The motion will feel more natural than an abrupt change.

The effect combines “Page Rearrangement” with “Scheduling”. A loop runs for the second of mutation progresses, with each transition occurring perhaps once every 50 milliseconds. Each transition will likely involve a gradual change to the positioning style settings, usually top and left. The position style can be set as absolute or relative, depending on the overall application design.

When an element has to move from point A to point B, in most cases, it's logical for the trajectory to be the shortest distance from A to B, i.e. for the element to move as the crow flies. The algorithm in this case uses interpolation; for example, one-quarter of the time into the effect, an element will be one-quarter of the way between A and B; so, when moving from left to right, the the left style of the element will be (0.25*x(A) + 0.75*x(B)), where x() represents the source and destinations' horizontal co-ordinate.

This assumes a linear interpolation, and you can also experiment with other algorithms, e.g. you might like to accelerate the element as it proceeds, which is often a more realistic model.

Note that you probably won't have to hand-code motion, because libraries like Scriptaculous (discussed below) are quite flexible and usually easy to incorporate into typical scripts.

Decisions

What events will trigger a motion effect?

One-Second Motion is not very common today, but there are several potential applications. First, a permanent movement can show any of the following:

  • A straightforward change from one place to another.

  • One element being spawned from another, and then jumping out to a new location.

  • An element being introduced into a space. Instead of the element just appearing, or fading in, you could make it arrive from a logical starting point. For example, a new data point in a chart can "fly in" from the corner.

A temporary movement has its own applications:

Attention-grabbing

For general attention-grabbing, motion is literally a killer app - humans are wired for sensitive motion detection as a means of surival. We've all seen enough annoying banner ads to know that. Extreme cases involve rapid vibration and rapid circuitous movement, such as tracing out a square 10 times a second. Of course, these extremes are rarely justified, and you can often use more subtle approaches to get the same effect (with a lot less annoyance factor).

Aesthetic effect

People expect an object to move in a certain way, based on experiences in the physical world as well as learned expectations from conventions in movies, cartoons, and video games. For example, when a small object bumps into a big object, you expect the small object to fly off in the other direction, and the big object to shake a little.

Gesture

Some forms of motion rely on anthopomorphisation - endowing the element with human-like characteristics, something users are surprisingly prone to do ("The computer doesn't like me today!"). In the Scriptaculous demo (discussed below), the search form shakes left and right when a validation error occurs, similar to a person shaking their head from side-to-side. Another effect would be to depict desire, by showing an element temporarily "reaching" in a certain direction, and pulling back again. This could be used as a hint to a novice user that they need to drag the element in that direction.

Since motion can be distracting, you will likely want to limit its usage to the following situations:

  • When the event is important enough to divert the user's attention to it.

  • When the user is likely to be focused on the motion already. Here, the motion is not used to attract attention, but rather to convey what's happening to the element.

  • When visualisation and motion is central to the application style; for example, if the application was tracking a car's movement every few seconds, it would probably be worthwhile animating the move between sample points.

Also, consider whether you should use motion at all. The conventional wisdom is that motion is more natural as a transition because it's based on the physical world. But how about the massive population who grew up with computers and might be perfectly comfortable with the sudden jumps that are only possible in a digital realm? Maybe not everyone will appreciate it.

What will the element do when it reaches its destination?

In every example case I've seen, the element stops suddenly at its destination. However, it might appear more natural to show some reverberation if the element ends up stacked against another element.

Real-World Examples

Scriptaculous Library

As mentioned in “One-Second Spotlight”, Scriptaculous is a general-purpose Javascript library. The visual effects demo supports motion-based effects.

TiddlyWiki

As detailed in “One-Second Mutation”, clicking on a TiddlyWiki “Microlink” causes the entire content to "leap out" from the link and form in a new position.

Backbase Portal

The Backbase Portal Demo contains a page full of “Portlet”s, arranged in three columns, each with its own menu. The menu contains all “Portlet”s on the page, and choosing a “Portlet” causes it to move over to the top of the column. “One-Second Motion” is used to animate the “Portlet”'s movement, allowing users to see that the “Portlet” has "flown in" to the top of a column from elsewhere on the page.

DHTML Lemmings

As detailed in “Sprite”, DHTML Lemmings involves the movement of Lemming creatures through a game space. Each Lemming is represented as a DOM element.

MS-Windows

MS-Windows uses a form of One-Second Motion. When minimising a window, the whole window appears to leap downwards to its handle in the taskbar, like a large object being packed into a small container. The reverse process occurs upon activating the window. This is not an Ajax App, but is still significant, as its frequently cited as rationale for the kind of animation this pattern details.

Code Example [Scriptaculous Effects].

Motion is one of the effects offered by the Scriptaculous effects library. Examining its implementation gives us an opportunity to look at the overall Scriptaculous effects engine, which also provides “One-Second Spotlight” and “One-Second Mutation”-style effects [16].

The generic engine component controls the flow, by continuously delegating to an individual effect object to perform an incremental animation. This is an example of the Strategy pattern (Gamma et al., 1995). The initialisation sequence clears the frame count, computes the total effect time, and kicks off the loop:

    start: function(options) {
      ...
      this.currentFrame = 0;
      this.startOn      = new Date().getTime();
      this.finishOn     = this.startOn + (this.options.duration*1000);
      ...
      if(!this.options.sync) this.loop();
    }

The loop runs until the predicted finish time, at which time the animation cleans up and terminates. The most important thing here is the pos calculation, which determines how far along the animation is. The calculation is essentially: timeSoFar/ timeRemaining. So, one-quarter of the way through the animation, it will be 0.25. Next, a calculation takes place to support the fps option, which lets the caller state the maximum number of animation frames per second. If an animation is indeed required, the engine's render() function is called:

    loop: function() {
      var timePos = new Date().getTime();
      if(timePos >= this.finishOn) {
        this.render(1.0);
        ...
        return;  
      }
      var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
      frame = Math.round(pos * this.options.fps * this.options.duration);
      if(frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
      this.timeout = setTimeout(this.loop.bind(this), 10);
    },

The main purpose of render() is to delegate to the effect strategy to perform the update. The strategy will receive a value between 0 and 1 to tell it how far the animation has proceeded.

The MoveBy effect takes a DOM element and tracks its start and end position. The element's style is set to relative using a call to the effect engine's makePositioned(). Because positioning is relative, you construct a MoveBy effect with relative arguments. To move an object 5 right and 10 down, you'd pass in 5 and 10 as parameters. The effect is to increase left by 5 and top by 10:

    initialize: function(element, toTop, toLeft) {
      this.originalTop  = parseFloat(this.element.style.top || '0');
      this.originalLeft = parseFloat(this.element.style.left || '0');
      this.toTop        = toTop;
      this.toLeft       = toLeft;
      Element.makePositioned(this.element);
      ...
    }

Remember that the effects engine delegates to update() for effect-specific behaviour, passing in a progress ratio between 0 and 1. In the case of MoveBy, the algorithm performs the necessary interpolation calculation to see how far along the object should be (topd and leftd). Having made the calculation, all that remains is to update the DOM element's style:

    update: function(position) {
      topd  = this.toTop  * position + this.originalTop;
      leftd = this.toLeft * position + this.originalLeft;
      this.setPosition(topd, leftd);
    },
    setPosition: function(topd, leftd) {
      this.element.style.top  = topd  + "px";
      this.element.style.left = leftd + "px";
    }

The MoveBy effect is useful in itself, to get an object from A to B. But you can build on it to create effects such as motion displacements. One such effect, included with Scriptaculous, is Shake(), which swings an element left and right a few times. With the framework in place, the effect is easily defined as a sequence of moves:

    Effect.Shake = function(element) {
      return new Effect.MoveBy(element, 0, 20, 
        { duration: 0.05, afterFinish: function(effect) {
      new Effect.MoveBy(effect.element, 0, -40, 
        { duration: 0.1, afterFinish: function(effect) { 
      new Effect.MoveBy(effect.element, 0, 40, 
        { duration: 0.1, afterFinish: function(effect) {  
      ...
    }

Alternatives

“One-Second Spotlight” and “One-Second Mutation” are also used to draw attention to a significant event. One-Second Motion is suited to indicating an object's state has changed where there is some geometric mapping to each object's state. When used as a temporary displacement effect, the effect is sometimes an alternative to these other patterns.

Related Patterns

A “Sprite” often undergoes motion similar to One-Second Motion, and can make use of similar interpolation calculations.

In some cases, the motion is a form of “Guesstimate”. When an object is moving around according to state information, the motion effect is effectively an estimate of what's happening between positions.

Metaphor

Until "Beam Me Up" teleportation technology hits the markets, every visible movement in the physical world is an illustration of this pattern.



[16] Note that the engine code looks a little different to most JavaScript applications because it uses Prototype to allow for a more object-oriented coding style.

Live Wiki Version for One-Second Motion