One-Second Mutation
From Ajax Patterns
There's an archived version of this pattern available, taken from the Ajax Pattern book draft, showing roughly how it appeared before the page became publicly editable.
Evidence: 3/3
Tags: Auto-Update Sync Synchronise Sychronize Real-Time
Contents |
Ajax/Javascript Programming and Usability in "Ajax Design Patterns" Book |
In A Blink
Object gets smaller and vanishes.
So I'll stop notating these, since we're going to tighten up how they all look.
Goal Story
Doc is watching a historical visualisation of a patient's medicine intake, where each drug being taken at a particular point in time is represented by a small label on the web page.First sentence seems a little stiff. Each time a drug appears, a one-second Something missing in the text here?, the label appears to "unroll" from the a single from the initial line? line, as if it were a scroll. And when it disappears What is "it"?, the label rolls up again.
Problem
There's a lot of activity in an Ajax application - how can you help the user digest it all?
Forces
- To ensure the user is working with current data, the browser display must be frequently updated.
- With Ajax, it's possible to update only the portion of the screen that has changed; if nothing has changed, the display remains exactly as is.
- The screen can get cluttered with a lot of information, much of which might be changing at any time.
- While human vision is good at spotting changes, it's easy to miss a sudden change, especially if the change is a subtle one.
- Even worse, there are different types of changes, and those differences are important to users.
Solution
When a page element undergoes a value change or some other significant event, dynamically mutate its shape for a second or so. In most cases, the mutation is used to reflect a permanent change. Instead of flipping from one form to another, the element gradually transitions into another form. The effect serves a couple of purposes:
- The mutation and the extended transition time make it likely the user will notice that something's happened.
- The type of mutation will hint at what sort of action has taken place.
- The gradual appearance will feel more natural than a sudden mutation. This one confused me; aren't you in fact describing a mutation, not an appearance? Or do you mean a gradual mutation will feel more natural than a subtle one?
The effect combines Display Morphing with Event Scheduling. A loop runs while the second of mutation progresses Didn't get all of this one; does this mean the mutation lasts a second? Since you haven't said thay anywhere explicitly, it's unclear, with each transition occurring perhaps once every 50 milliseconds. Each transition will likely involve a change to at least one of the following CSS properties:
- width - An object can be thinned or fattened with its width value.
- <height - An object can be heightened or shortened with its height property.
- background-image - Instead of just resizing the element, it's possible to swap in a completely different image. Just like a movie, the DOM element quickly flips through various images to give the illusion of mutation.
- position - Manipulation position with position, left, right, top, and bottom is necessary In other bullets, you talk more about what is possible; here you just say what is neccessary for certain mutation effects.
- overflow - Overflow can be set to hidden to enable the entire element to be present on the page, but only show a certain portion of it.
The first category involves making an object appear. What is the first category? Do you mean the first list? Or this next list, which I think -is- what you mean? These can be effective ways to communicate the object has just been created or retrieved from the server.
- Form - An item "forms" from nothing to its standard appearance, typically by incremental, outward, growth. It might grow from the centre of the object, or a corner, or some other position entirely. Typically, width and height increase at the same time.
- Slide Out - An item slides out. If the item slides in from the side, it appears to be pushed out like a sliding door. If the item comes in from the top, it appears like a garage door being unrolled. If coming in from the bottom, the item appears to rise from the ground. Usually either width or height is fixed, while the other dimension gradually increases, all while the position also changes.
- Reveal - An item is gradually revealed. It appears that the item has been there all along, and a cover is gradually being lifted off. Here, one or both of width and height incrementally increases, while overflow is set to hidden so that part of the element is covered.
This next category involves some common disappearing acts--the opposite of the effects above--and a special effect for disappearing:
- Disappear - An item changes from its standard appearance to nothing.
- Slide In - An item slides in to To the top? or from the top? the top, side, or bottom.
- Cover Up - An item is gradually covered up in one or both dimensions.
- Blow Up - An item expands outward from its current side, and simultaneously fades out to nothingness.
There are also a few effects that involve changing from one thing to another:
- Grow - An item grows from one size to another. Height or width (or both) increases.
- Shrink - An item shrinks from one size to another. Height or width (or both) decreases.
- Metamorphise - An item shifts from one appearance to another. This is typically achieved with a change in background image. See Sprite for more details.
Most of these effects can be combined with One Second Spotlight to give a 3D effect. For example, an item can Materialise and Form at the same time. The human visual system uses both ambience and size as cues for distance, so the effect is that the item is reaching outward from behind the screen and towards the user.
Note that you probably won't have to hand-code effects, because libraries like scriptaculous (discussed in add a link here) are quite flexible, and usually easy to incorporate into typical scripts.
Decisions
Most of the decisions in One-Second Spotlight are relevant here too. As with One-Second Spotlight, the "One Second" name is only a guideline.
Real-World Examples
TiddlyWiki
Jeremy Ruston's Tiddlywiki, like many of its spinoffs, uses a Grow effect to introduce some new content when you click on a Microlink. The Microlink itself is the starting point, and the new content block appears to leap out and, as it flows outward, grows into a full microcontent block. Actually, there are a few visual effects at work here:
- One-Second Spotlight is used to fade in the microcontent being opened, in parallel to the element leaping out.
- One-Second Mutation is used to grow the transition element from its initial state as a small piece of link text into a full block of microcontent.
- One-Second Motion is used to move the element from the Microlink position into the microcontent below.
There are a few variations possible, depending on whether the content is already open and where it's placed.
Scriptaculous
As mentioned in One-Second Spotlight, scriptaculous is a general-purpose Javascript library. The visual effects demo provides many of the mutation effects described here.
DHTML Lemmings
DHTML Lemmings is a full-featured implementation of the Lemmings PC game, which uses DOM manipulation to show the lemming creatures performing various lemming-like activities, such as walking, digging, and clutching an umbrella to safely descend downwards (muh like a Hollywood spy). As the characters move along, their appearance is animated using quick mutations. While the usage is somewhat different from the usual type of mutation--which tends to focus on highlighting particular pieces of information--it is still of particular interest because it involves manipulation of images instead of just CSS style. See Sprite for more details.
Code Examples
TiddlyWiki
Let's look at how TiddlyWiki shows the Grow effect discussed above. In doing so, we'll see how its generic animation engine works.
TiddlyWiki delegates animation to an Animator class, which is capable of animating according to a strategy (see Gamma et.'s Design Patterns for more on the Strategy pattern) known as animations. At this time, there are a couple of animation classes: a Zoomer and a Slider. In the context of TiddlyWiki, the animator is a singleton--only one animator is defined for the entire application. That's because the animator keeps a list of all running animations running at any time:
var anim = new Animator();
function Animator()
{
...
this.animations = []; // List of animations in progress
return this;
}
When a Microlink is clicked, the animator is passed a Zoomer strategy, which is injected with the microlink DOM object from which the content will leap out(src), a string title of the microcontent (title), the microcontent DOM where the content will end up (theTiddler), and an a flag indicating if the animation should be slow or not (I assume this is for debugging, and you can activate it by holding down shift or alt as you click on the link):
anim.startAnimating(new Zoomer(title,src,theTiddler,slowly));
startAnimating() pushes the new animation onto the list of running animations. If not already running, it sets up an animation loop:
Animator.prototype.startAnimating = function(animation)
{
this.animations.push(animation);
if(this.running++ == 0)
{
var me = this;
this.timerID = window.setInterval(function() {me.doAnimate(me);},25);
}
}
The loop runs every 25 milliseconds. It calls a tick() function on each running animation. By analysing Zoomer's tick(), you can see how the One-Second Mutation is achieved. On construction, Zoomer has already set up a bunch of variables to support this function, as well as an element (element) to be shown during the transition. The variables hold position information about the start DOM object and the end DOM object. tick(), then, is left with the task of interpolation: "if the item starts at point A and ends at point B , how should it look at a particular point in the journey?" The animator provides a value between 0 and 1 to define how far along the animation the object is, which makes things much easier. So, if the value is 0.5, the item's width will be halfway between the original width and the item's final width. The same idea applies for height and position:
this.element.style.left = this.startLeft + (this.targetLeft-this.startLeft) * f + "px"; this.element.style.top = this.startTop + (this.targetTop-this.startTop) * f + "px"; this.element.style.width = this.startWidth + (this.targetWidth-this.startWidth) * f + "px"; this.element.style.height = this.startHeight + (this.targetHeight-this.startHeight) * f + "px";
A One-Second Spotlight effect is also used here, as the target object--the place where the object is "leaping" towards--gradually fades in, using the opacity property (and filter, for compatibiity). Finally, the window is scrolled to show the target object:
this.targetElement.style.opacity = this.progress; this.targetElement.style.filter = "alpha(opacity:" + this.progress * 100 + ")"; window.scrollTo(0,this.startScroll + (this.targetScroll-this.startScroll) * f);
The purpose of mutations is generally to provide a smooth transition from one state to another. Therefore, the final state should generally be reached simply by running the animation for the right period. No special handling needs to take place at the end, right? Well, in practice, that turns out to not work very well. First, there's some cleanup to take care of Like what? Be specific here.. Secondly, there are rounding errors and approximations which make it good practice to explicitly set the final state. (The Time Spotlight demo, explained in One-Second Spotlight explicitly sets the final colour, for instance). Finally This following bit reads like it handles the two tasks you just mentioned. I guess this section was a little oddly constructed; can you take a second look?, the Zoomer deletes the DOM object it had created to leap from source to target, and then ensures the target's opacity and window scroll setting are in their final state. (The filter should ideally be set here too, but the final state after all the ticks is close enough not to make much difference.)
Zoomer.prototype.stop = function()
{
this.element.parentNode.removeChild(this.element);
this.targetElement.style.opacity = 1;
window.scrollTo(0,this.targetScroll);
}
Alternatives
One-Second Spotlight and One-Second Motion
One-Second Spotlight and One-Second Motion are also used to draw attention to a significant event. One-Second Mutation is particularly suited to indicating certain types of changes have occurred, such as object creation and removal, as opposed to general-purpose attention-grabbing.
Related Patterns
Sprite
Sprites are often changed in rapid succession to give the impression of a smooth transition.
Visual Metaphor
Many of the individual effects have their own metaphors - that's why they're used! Slide Out looks like an physical object sliding outwards, Grow looks like an object being stretched, and so on.
Want to Know More?
Acknowledgements
Many of the effects discussed in the Solution are based on an analysis of the Scriptaculous implementation. Jeremy Ruston's TiddlyWiki code was also instructive, and Jeremy helped clarify an aspect of the code for me.
Time your website with
WebWait - from the creator of AjaxPatterns.org
