Animation
Animation
Basics
"Animation" creates a transition effect on the interface over a period of time by playing several frames continuously and rapidly. There are two ways to implement animations in Glyphix:
- Carousel animations by rapidly playing a set of images;
- Keyframe animations where the program automatically calculates intermediate frames.
Keyframe Animation
Carousel animations are implemented through specialized components, and their principle is similar to video. This section mainly introduces keyframe animations. The following example demonstrates a keyframe animation:
To implement this animation, developers need to define the starting frame (red text) and the ending frame (green text) of the animation. The program then automatically calculates every frame in between. The starting and ending frames specified by the developer are called keyframes, and keyframe animations also allow for defining intermediate keyframes. Frames calculated by the program are called interpolated frames. In this example, the starting keyframe is the original text component, while the ending keyframe translates the text by and scales it by . Interpolated frames are intermediate transformation values calculated based on the animation progress. For example, the interpolated frame when the animation reaches translates the original text by and scales it by .
Compared to carousels, keyframe animations are easier to create and are suitable for transition effects of interface elements (such as button press animations).
Keyframe animations are mainly defined by several elements:
- Keyframes: Manually specified frames; typically, keyframes are used at and progress;
- Animation duration: The time required for the animation progress to go from to ;
- Easing function: Defines the progress adjustment curve for interpolated frames; linear animation effects often have a poor visual feel;
- Iteration count, delay, playback direction (normal, reverse, alternate), etc.
Property Animation
Keyframe animations used in Glyphix are primarily property animations. That is, keyframes are defined by element properties, and interpolated frames calculate intermediate property values. For example, like the animation implemented by the transition property modifier: the animation system automatically handles the transition effects of property changes.
Property animations are mainly divided into two categories:
- Component property animation: Adds animation transitions to component properties, implemented by the
transitionproperty modifier; - CSS animation: Adds animations to style properties.
Easing Functions
Easing functions define the adjustment curve of animation progress, thereby avoiding monotonous linear interpolation effects. Readers can visit https://cubic-bezier.com/ to experience the effects of easing functions.
In the transition property modifier and the CSS animation property, the easing function is a string, the content of which is shown in the table below.
| Value | Description |
|---|---|
ease | Default value. The animation starts slowly, then speeds up, and slows down before ending. |
ease-in | The animation starts slowly. |
ease-out | The animation ends slowly. |
ease-in-out | The animation starts and ends slowly. |
linear | The animation has the same speed from start to end. |
spring | Simulates a spring rebound animation effect, equivalent to spring(1,1,1). |
cubic-bezier(x1, y1, x2, y2) | Defines an easing function using a cubic Bezier curve. |
spring(spring, damping, mass) | Simulates a spring rebound animation effect, allowing specification of the stiffness, damping, and mass parameters (documentation required). |
For most animations, the ease easing function yields good results, while complex requirements can use the cubic-bezier() function. The spring() function is suitable for scenarios requiring rebound physical effects, such as pointer rotation.
Examples
Button Animation
As shown below, the default button effect has no press animation:
<div>
<button>Button</button>
</div>
button {
display: block;
background-color: #8af;
padding: 8px 16px;
border-radius: 50%;
margin: 16px;
}
button:active {
transform: scale(1.1, 1.1);
}
You can use the CSS animation property to add interactive animations to this button:
<div>
<button>Button</button>
</div>
/* Define active pseudo-class keyframes. When from / 0% keyframes are
omitted, the animation starts from the component's current state. */
@keyframes button-active {
to {
transform: scale(1.1, 1.1);
}
}
/* Define normal keyframes. When from / 0% keyframes are omitted, the
animation starts from the component's current state. */
@keyframes button-normal {
to {
transform: scale(1, 1);
}
}
button {
display: block;
background-color: #8af;
padding: 8px 16px;
border-radius: 50%;
margin: 16px;
/* Scale the button to 100% via animation in the normal style */
animation: 0.2s ease button-normal;
}
button:active {
/* Scale the button to 110% via animation in the active pseudo-class style */
animation: 0.2s ease button-active;
}
Currently, the CSS transition property is not supported, so animations must be defined separately in the button's normal style and active pseudo-class style.
spring Animation Effect
The spring easing function provides an interpolation effect similar to spring-damped vibration, which can be used for moving pointers. The following example demonstrates two methods for implementing pointer animations: the left side shows uniform pointer rotation, while the right side uses the spring easing function.
<div class="window">
<div class="clock">
<div class="pointer"
transform="translate(0, -40%) rotate({{angle}}deg) translate(0, 50%)"
transform.transition="{curve: 'linear', duration: 1}" />
<div class="pointer invisible"></div>
</div>
<div class="clock">
<div class="pointer"
transform="translate(0, -40%) rotate({{angle}}deg) translate(0, 50%)"
transform.transition="{curve: 'spring(1.2,1,1.2)', duration: 1}" />
<div class="pointer invisible"></div>
</div>
</div>
.window {
display: flex;
}
.clock {
background-color: gray;
border-radius: 50%;
flex: 1;
margin: 4px;
}
.pointer {
background-color: #0f0;
width: 12px;
height: 50%;
margin: 4px auto;
border-radius: 50%;
}
.invisible {
visibility: hidden;
}
export default {
data: {
angle: 0
},
onInit() {
setInterval(() => this.angle += 5, 1000)
}
}
Both of these animations update the pointer angle at -second intervals, but the transition modifier of the component attribute will automatically add a rotation animation.
