Homepage Animations
Historical reference
My entry to web development was through Flash animation. My first two iterations of this site were authored in Flash if you dare to find and install the old Flash player plugin: bb1, bb2. When web 2.0 and the HTML5/CSS3 spec came out, I shifted to learning more about browser standards. Over time, Flash projects became fewer and DOM projects became my bread and butter. Eventually Flash became notorious as a security risk, and Adboe planned for sunset and ultimately killed the Flash browser plugin… 💀
Through the years, I never lost interest in animation. I dabbled in some different JS and CSS animations but never really got back to the full glory of Flash’s rich UX. After all, animation was the primary function of Flash and the animation stage and timeline were dominant features of the IDE. Recently I found that Flash Professional was retooled as Adobe Animate and given the ability to export animations to browser native formats. But since the newly minted SVG logo is coded with class hooks in preparation for JS animation, we’ll see it through with Javascript.
Animation frameworks
I looked through a few articles on animation frameworks and landed on GreenSock Animation Platform (GSAP). I’ve worked with GreenSock’s TweenLite in the past so I had a bias, knowing the learning curve wouldn’t be too steep. After reading the articles to compare with others out there, seems like GreenSock is still the champ. I also looked at performance metrics when to ensure I could accommodate mobile renders. The info I found online indicated that GSAP is also the perf winner. But GreenSock has a Timeline API and development maturity that also couldn’t be beat.
npm install --save gsap
import { gsap } from 'gsap';
Programmatic timeline
I’ve never seen an animation/video/audio program without a timeline. Audio/video players also contain this metaphor as the scrubber and playhead. In these programs, the timeline represents the arrow of time where you add various objects to the timeline. The playhead passes from left to right, activating those objects as they come into frame. GSAP converts this metaphor into an API.
const tl = gsap.timeline();
const duration = 0.5;
tl.to(el, { duration, x: 100 }, 1);
tl.to(el, { duration, y: -100 }, 2);
In a visual animation program, an animation typically starts and ends at a “keyframe”. I.e., create a keyframe on the timeline where the animation starts and another where the animation ends. These are the “start keyframe” and the “end keyframe”. And the time between the keyframes where the object transforms is called the “tween”.
The GSAP timeline convention is “position” and “duration” instead of “start” and “end”. The last argument in the to
method is the “position” or location on the timeline in seconds. This represents the “start keyframe”. The “end keyframe” would be the (position + duration):
Given the signature:
to(element, options{transform duration}, position)
We can derive the start and end keyframes:
Keyframe | Mapping |
---|---|
start | position |
end | position + options.duration |
In the above example, the sequence is:
- At the 1 second mark, the element animates to the right 100 pixels for 0.5 seconds.
- At the 2 second mark, it animates up 100 pixels for 0.5 seconds.
Which translates to “start” and “end” keyframes:
# | Transform | Start | End |
---|---|---|---|
1. | x motion | 1s | 1.5s |
2. | y motion | 2s | 2.5s |
Reverse time sequence
Another feature of GSAP is the from
method. Here you take an existing object and tween “from” any position/property back to the original position/property. In my case, I wanted the final state of the animation to be the fully formed logo. So the from
method was gold. I could work from the last frame of the animation back to the beginning using the from
method.
const tl = gsap.timeline();
const duration = 0.5;
tl.from([ascender_1, ascender_2], { duration, x: 0.1, y: 6.1 }, 0.5);
tl.from([ascender_1, ascender_2], { duration, stroke: 'transparent' }, 1);
tl.from([bowl_1, bowl_2], { duration, stroke: 'transparent' }, 1);
tl.from([counter_1, counter_2], { duration, opacity: 0 }, 1.3);
Here is the sequence above explained:
- The ascenders are tucked “from” their original extended position into the bowls to form a full hexagon. This transformation will start to “unfold” back to the ascenders’ original positions at the 0.5 second mark on the timeline.
- The ascenders’ and bowls’ strokes are faded “from” transparent back to their original colors at the 1 second mark.
- The counters’ entire elements are faded “from” transparent to opaque at the 1.3 second mark.
Which can be translated to start and end keyframes:
# | Elements | Transform | Start | End |
---|---|---|---|---|
1. | ascenders | {x,y} motion | 0.5s | 1.0s |
2. | ascenders | {stroke} opacity | 1.0s | 1.5s |
3. | bowls | {stroke} opacity | 1.0s | 1.5s |
4. | counters | {opacity} | 1.3s | 1.8s |
Check out the homepage to see it in action!