We've got feedback on the Rotating Banner widget
and that the users sometimes need more than just
simple fading effect
. Well, a fancy visual effect doesn't necessarily require more system resource.
We have once again honoured our low carbon tradition, and created this banner widget that slides like a train.
- Each slide supports full HTML
- Animation automatically starts
- Inherits user controls
- Animation avoids intefering user interaction
- Uses very little CPU
As you can see from the source code of the demo page, this widget is very easy to use.
You need to declare two markup sections: one is the view of the sliding banner, and the other one is the data source.
It's important to style the data source invisible, and make the slider "clip off" its content.
You can place additional custom controls inside the slider container. They will be automatically replaced on top of the slides.
The slider is started by calling:
You can manually move the slider to the left or right by calling the following function:
The second parameter takes the value of 1 or -1 for moving to the left or right respectivley. The third parameter tells the auto play to pause for 2 iterations,
so that the animation doesn't intefere with user interaction.
A Peek under the Hood
If you are one of those curious minds, please keep reading about some worth noting design decisions made in this script:
When the slider is first loaded, it maps the child nodes in the data source to an internal representation.
Slides, or "cells" in the slider are dynamically spawned as child nodes of the slider container.
If there are existing nodes inside the slider container, they are temporarily removed and added back,
so that they stay on top of the slider cells. Note this DOM rewrite only happens at load time, so it doesn't cost resource to run.
You have probably seen some other train sliders that moves to the last slide, and the "jumps" all the way back to the front. How awkward!
This slider doesn't do that. The train cycles through each cell in the deck of slides infinitely.
To realize this effect, I used three tricks. One is to use three cells to display the current slide, and the slides that are before and after.
The slider container clips out the other two slides. When the parent container of the cells move, all the cells move together.
The second trick is to make the cells rotate. If you peek inside the code, you'll see these cells are called A, B and C.
When the slide moves to the right, the left-most cell jumps to the right, making the sequence to B, C and A.
Since the jump happens in the clipped-out area, the switch is not noticable to users.
The third trick makes cell sequencing easier. It uses virtual cell pointers. At the end of each cell rotation, the cell pointer will rotate in the reverse direction.
The result is that not only the end users cannot see the "jump", the program itself cannot see it either! The same code then handles all the permutations of cell arrangements, in both directions.
Animation Keyframe Generation
Animation takes the lion's share of CPU usage in most other sliding widgets.
Here's the secret to avoiding excessive computing: having as few key frames as possible, without degrading too much "smoothness".
The human eyes perceive motion easily, but are not sensitive to the details of the motion. In other words, we can miss out some insignifant
frames, and the users can fill them in subconsciously. To further hide the missing frames, the cells move by exponentially decreasing offsets, instead of shifting linearly.
As a bonus for readers of the code, I implemented an autoplay that unlocks itself. When the slide_move
function is called with the interrupt flag,
a lock is created in the slider container. The animation sequence skips a round when the lock is still present. The lock is also a handle to a self-expiring timer,
which, interestingly enough, removes the lock after 2 slide intervals.