First put on the effect diagram, and then the implementation method.

Expression changes



C0, 0,0,0,0,0
Juejin. Cn/post / 684490…


1. Separation of static and static

No matter what form of SVG GIF, the first step is naturally inseparable from our “static and static separation method”. The static diagram is separated as follows:

A static image,









<g id="base">... Corresponding static base map code... </g> <g class="emotion">
<path id="left"/>
<path id="right"/>
<path id="mouse"/>
</g>Copy the code

“Left” is the left eye path (since sad’s left and right eyes are symmetric, there is no definition of a set of animation multiple references); “Right” is the right eye path; Mouse “is the mouth path. To make it easier to define stroke attributes, I put all the expression elements into a group. So I can do this by defining CSS properties

.emotion path{fill:none; stroke:# 615658; stroke-width:6; stroke-linecap:round; stroke-linejoin:round; stroke-miterlimit:10}Copy the code

To give all expression elements the same stroke effect.

2. Implementation of the first animation

Let’s start with how the eyes change from round to curved. The first thing to be sure of is that it’s definitely a morphing animation. The curved curve only needs one path to achieve, while the circular path has four paths, so what we need to transform is the curve with fewer paths. The method is also very simple, just add three anchor points to make it become four paths. Also use scissors to cut open circular paths. Other details to pay attention to the adjustment method is not detailed, the transformation of animation in three articles are detailed.

Eye animation 1 implementation method

@keyframes deformLeft1{
0% {d:path(' '} /* circular path */ 100%{d:path()' '} /* The crooked path when laughing */}#left{animation:deformLeft1 1s ease}Copy the code

In this way, the deformation animation of the left eye is realized. This animation process does not add virtual curves directly to curves with few paths because it does not work well after trying. The mouth process is a straight line to curve process, AI directly derived from the line must be like the following

<line  x1="" y1="" x2="" y2=""/>Copy the code

The slightly upturned mouth corresponds to the path tag . What we need to do is to convert the line starting point (x1,y1) and ending point (x2,y2) into a path label. The method is also very simple, corresponding to the d values Mx1,y1c0,0,0, (x2-x1),0.

Mouth animation 1 implementation method


@keyframes deformMouse1{
0% {d:path(' '{d:path() {d:path();' ')} /* Slightly upturned mouth path */}#mouse{animation:deformMouse1 1s ease}Copy the code

This completes the first animation process. During path modification, use either method to retain the unmodified path. The reason will be revealed later.

3. Implementation of the second animation

If not, change the line to a curve with very, very, very, very little handle. When we finished the last animation, we changed the eye curve from one path to four to match the circle, so what happens here? Should I cut the sad eye into four pieces, well, even if it could be done here, then the spiral of the dizzy eye? It is composed of N paths, do you want to take the final number of the most path prevail, add anchor points added to soft cramp? ! That’s why you want to keep an unmodified path. We will use the original path directly, because sad Eyes is two paths, so add an anchor point to the original path to make the path from one to two. No matter how many anchors are added to the path, there is no visual difference, so the animation can achieve seamless stitching.

Animation 2 Eye deformation animation implementation

@keyframes deformLeft2{
0% {d:path(' '} /* Change into two paths of crooked eyes */ 100%{d:path()' ')}/* Sad eyes */}Copy the code

We append multiple animations to an element using the following syntax:

#left{animation:deformLeft1 1s ease,deformLeft2 1s ease 1s}Copy the code

Because I set the completion period of the first animation to 1s, so the last 1s of the second animation deformLeft2 means that the execution will be delayed for 1s. The reason why I didn’t define multiple keyframes to realize multiple deformation animations is that there are too many spiral paths in the end. Of course, the most important thing is that I use the ease function to add a little pause to each animation. For the second animation, the mouth deformations are simple enough not to go into detail.

4. Implementation of the third animation

The number of paths in the animation deformation process is quite different, of course, how can we be baffled by this problem, there are only two paths for sad eyes, and there are fully seven paths for spiral eyes, the difference of five paths let us universal virtual curve c0,0,0,0,0,0 to achieve it, so easy!

Animation 3 Eye deformation animation

Because there are too many circles here, I will change the stroke-width as well.

@keyframes deformLeft3{
0% {d:path(' '} /* c0,0,0,0,0,0*/ 100%{d:path(' '); stroke-width:4} }Copy the code

Continue to append the defined animation deformLeft3

#left{animation:deformLeft1 1s ease backwards 1s,deformLeft2 1s ease 1s,deformLeft3 1s ease 2s forwards}Copy the code

The only difference here is THAT I add forward. The property value of this animation property is animation-fence-mode, which defines the state of the animation after the animation is finished. Forward means the last property value is kept after the animation is finished. Why add this property? Because from the beginning, our eyes and mouth elements are not reflected in the code, all by animation properties draw path to add, and the next group of eyes animation is rotation, if the circle after the eyes do not define the animation state after the end, in the rotation animation, animation element is empty. The morphing animation of the mouth is also relatively simple. Just add anchor points to the downward curved path of sadness and complement the number of paths corresponding to the forked mouth.

5. Implementation of the fourth animation

The eye rotation animation is simple to implement, but we need to define the rotation center of transform-Origin, not default to the origin of the upper left corner of the canvas.

@keyframes deformLeft4{
0%{transform:rotate(0); transform-origin:}
100%{transform:rotate(360deg); transform-origin:}
}Copy the code

This value is obtained directly from the AI.

Center of rotation


#mouse{animation:deformMouse1 1s ease,deformMouse2 1s ease 2s,deformMouse3 1s ease 3s forwards}Copy the code

Ok, the above is the realization process of all animation, so finish such a set of dynamic changes of expression can be used in what place? This is the magic of our “static separation method”, you just need to change the static base image, you can get different effects. And I can change the color. It’s awesome.

6. Application of different base maps

For example, I once made a set of square emoticons, which look like this

Square emoticons

Now, I want the second heart icon in the first row to become a dynamic emoticon. Just overlay our animation and scale it with SVG width, height and viewBox properties to get the following square emoticon:

A square face

Other applications are no longer one by one examples, on sauce.