Hi, this is Yuki, UX (Interactive Experience Designer) & Front-end development, and she loves painting! @ yuneco. In this article, in order to use Vue and CSS animation more easily, the basic part will be explained step by step in detail. The target is shown in the β figure below, and you can control the animation freely with JavaScript.
Send the source to github.com/yuneco/css-…
directory
So start with the simplest SVG tag. Configure and deform them freely with Vue. Then use CSS transition to animate, and finally abstract and encapsulate the animation to apply it to more complex scenes.
- Production of SVG
- Create a Vue project
- According to the SVG
- Free configuration
- Be able to change more freely and at a larger Angle
- Give the animation
- Able to animate continuously
- Abstract encapsulation animation
Pay attention to the point
- The methods described in this article are not generic when using animation.
- For more complex animations, use the
anime.js
orpixi.js
. - This article does not use a dedicated animation library, but a self-encapsulated animation. The goal is to gain a deeper understanding of Vue,
javascript
,CSS animations
.
There are a lot of reasons, but it’s definitely nice to be able to light up my own skill tree for making animations that I can understand. It’s a little long, and I’d be glad if you could finish it.
Production of SVG
The first step, show this tutorial to use SVG, using Illustrator to make their favorite role to go, one by one from the menu to select [γ to the list] -> [book, a siqi] -> [while it belongs to the SAN book, the format select SVG, from the right gear like the icon, display setting.
The Settings look a bit complicated π, here in Vue there’s no trouble to make SVG, so the Settings here don’t need to care too much, the right bottom Responsive(γΉγγ³ γ γ) choice remember to remove.
The verbal Abuse saved “-> attract γΌγ deployMode the book usher out one of the SVG files. Those without Illustrator can use other files. For those of you who are afraid of trouble, I have also posted a copy on Github…
Open it in the browser, and that’s what it feels like. It’s called Tama SAN, and it’s just been decided. I added a 1 pixel border to make it easier to understand.
Create a Vue project
After all, you can’t get started without creating a Vue project. Run the vue Create project name to create the project, as shown below, or as you like.
? Please pick a preset: default (Babel, eslint) β― Manually select features? Check the features needed for your project: β Babel Infection infection TypeScript infection Progressive Web App (PWA) Support infection of Router infection Vuex β―β CSS pre-processors β Linter/Formatter infection Unit Testing infection of E2E Testing? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Use arrow keys) β― Sass/SCSS (with Dart-sass) Sass/SCSS (with Node-sass) Less Stylus? Pick a linter / formatter config: ESLint with error Prevention only ESLint + Airbnb config β― ESLint + Standard config ESLint + Prettier all defaultsCopy the code
Once the project is created, remove the extra HelloWorld components and run NPM Run Serve in the empty project to make sure it can run.
According to the SVG
/public/img/ if the img directory does not have one, create it yourself. Let’s start by rendering SVG in Vue.
Just plain SVG display has nothing to do with Vue. Also, for later purposes, create a SRC/Components/tama.vue file like this.
<template>
<img src="/img/tama.svg" alt="Table temp agistic code">
</template>
Copy the code
This tutorial uses the simplest way to read SVG, using the IMG tag. Of course, you can use other methods, such as the following:
- Use the < SVG > tag directly
- Use CSS background-image
- Use plug-ins such as VUE-SVG-loader to import into VUE components
Of course, there are various methods, especially scheme 1, which is great to use (colors and shapes can be controlled in Vue, etc.). If you want to make things more complicated, try this one. After the tama. vue component is built, introduce the display in app. vue.
// Tama.vue
<template>
<div id="app">
<tama></tama>
</div>
</template>
<script>
import Tama from './components/Tama.vue'
export default {
name: 'app'.components: {
Tama
}
}
</script>
<style lang="scss">
html.body {
margin: 0;
padding: 0;
}
body {
position: relative;
height: 100%;
background: url('/img/grid.svg') repeat;
}
#app {
margin: 0;
}
</style>
Copy the code
I’m just importing Tama here. After clearing out the default styles, the background is displayed in a grid for easy display. I’ll show it like this.
Configure it where you want it
The picture is already out, and if you can’t freely show it where you want, you can’t animate it. The next step is to deploy the tama mulberry anywhere.
Configure to the specified coordinates
Let’s start with x = 200px and y = 100px.
<template>
<img
class="tama-root"
src="/img/tama.svg"
alt="Table temp agistic code"
>
</template>
<style lang="scss" scoped>
.tama-root {
position: absolute;
left: 0;
top: 0;
transform: translate(200px.100px);
}
</style>
Copy the code
Position: absolute absolute positioning, then use the transform, the specified coordinates while the specified location can also use the top and left, but the use of CSS to do animation, or use the transform as far as possible. This is easy to do (among various other requirements) by specifying the location of elements, and the animation is silky and smooth when rendered by GUP.
Ok, done! Tama Sang’s position was successfully moved (200px, 100px)!
Huh? Wait π , clearly make the tama sang position at (200px, 100px), why the coordinate is based on the top left corner, and then draw the same position. Still want to use the soles of her feet as a baseline.
There are many ways, this time with margin to adjust it.
.tama-root{/ /...margin: -300px auto auto -90px;
}
Copy the code
Use parameters to control coordinates
Before using fixed coordinates, in actual use, will still want to change the words of the coordinate when adding animation. So of course it’s not dead in CSS, use Vue props to control.
// Tama.vue
<script>
export default {
name: 'Tama'.props: {
x: { type: Number.default: 200 },
y: { type: Number.default: 100}}}</script>
Copy the code
Append new code to tama. vue, add x and y parameters, and specify type and default as well.
// Tama.vue .tama-root { // ... margin: -300px auto auto -90px; // Delete: transform: translate(200px, 100px); }Copy the code
Then specify the style to use in template.
// Tama.vue
<template>
<img class="tama-root" src="/img/tama.svg" alt="Table temp agistic code"
:style="{ transform: `translate(${x}px, ${y}px)` }"
>
</template>
Copy the code
You can then specify the location of tama mulberry in app. vue where the reference is made.
// APP.vue
<div id="app">
<tama :x="300" :y="400"></tama>
</div>
Copy the code
Change Angle and size
Similarly, let’s change the scale and the Angle. If you can freely control the position, size, and Angle, you can create your own picture.
Use properties to control size and Angle
If you add things to the same place, scale can specify landscape or portrait, so I’m going to add scaleX and scaleY.
// Tama.vue
props: {
x: { type: Number.default: 200 },
y: { type: Number.default: 100 },
scaleX: { type: Number.default: 1.0 },
scaleY: { type: Number.default: 1.0 },
rotate: { type: Number.default: 0}}Copy the code
The scale and rotate attributes are also specified in transfrom. Scale minus units, rotate plus units of angles (DEG).
// Tama.vue
<img class="tama-root" src="/img/tama.svg" alt="Table temp agistic code"
:style="{ transform: `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY}) rotate(${rotate}deg)` }"
>
Copy the code
Then specify the properties in the referenced app.vue.
// App.vue
<div id="app">
<tama :x="300" :y="400" :scale-x="1.5" :scale-y="1.5" :rotate="45"></tama>
</div>
Copy the code
As easy as assigning a location! Huh? And so on…
The Angle and size do change, and the reference point is also a bit strange π
To solve this problem, use the transform-origin property of CSS.
// Tama.vue
.tama-root{/ /...transform-origin: 90px 100%;
}
Copy the code
Transform-origin can be in pixels or percentages, and then let’s specify the position of the tama mulberry.
Add animation
Finally… Once you’re ready to animate, start with a simple animation (click and jump 50px up), which is basically just clicking and changing the position of the Tama sonson y axis.
Click to change position
Animations can be added to tama. vue or app. vue. Here we want tama mulberry to have this function itself, so it’s more natural to do it in tama.vue, so I’ll just write it here.
// Tama.vue
<template>
<img class="tama-root" src="/img/tama.svg" alt="Table temp agistic code"
:style="{... }"
@click="jump(50)"
>
</template>.<script>
export default {
name: 'Tama'.props: {... },methods: {
jump (height) {
this.y -= 50}}}</script>
Copy the code
Call the jump method with @click on a click, set y to -50 inside, and when that’s done, click tama and it will move up 50px.
Unfortunately, the browser’s console has this warning.
Since y is specified by the parent component, you can’t change it here, (x, y) just specifies its position, so add relative positions inside.
First, to add variables internally, write data first, then add dx and dy variables. And then change the y in the jump method to dy.
// Tama.vue
<script>
export default {
name: 'Tama'.props: {... }, data () {return {
dx: 0.dy: 0}},methods: {
jump (height) {
this.dy -= height
}
}
}
</script>
Copy the code
Template is going to be equal to the base position (x, y) + the relative position (dx, dy).
// Tama.vue
<template>
<img class="tama-root" src="/img/tama.svg" alt="Table temp agistic code"
:style="{ transform: `translate(${x + dx}px, ${y + dy}px) ... `}"
@click="jump(50)"
>
</template>
Copy the code
Animate the change location
The position does change when you click, but it’s not animated yet. emm… Let’s go add animation. As for the method of adding animation, I consider the following two points.
- Use continuous timer to control y and dy coordinates.
- Set the coordinates in one breath and animate them in CSS.
The first point can control very complex animation, but every time you have to calculate the coordinates, it will become very troublesome. In point 2, as long as we specify the changed value, the browser will animate it for us, and it’s smooth.
I’m going to choose 2. You only need 2 lines of code.
// Tama.vue
.tama-root{/ /...transition: transform 1s ease;
will-change: transform;
}
Copy the code
Will-change is the “magic” that makes animation smoother. (I didn’t think it was a good idea to use “magic”, but I wrote another article about it: 60fps animation with will-change.)
When you do that, when you click on it, the tama will slide up. The simple animation is thus Μ Ο β’Μ)y.
Specifies the timing and easing effect of the animation
In the previous example, we specified the animation time (1s === 1 second), ease and write dead code. This is enough to specify animations, but let’s give her control over it.
Add duration and easing to data, and add those variables to template.
// Tama.vue
<template>
<img .
:style="{ transform: ... , transition: `transform ${duration}ms ${easing}` }"
@click="jump(50)"
>
</template>.<script>
export default {
name: 'Tama'.props: {... }, data () {return{...duration: 1000.easing: 'ease'}},... }</script>
Copy the code
Continuous animation (one animation is finished and the next animation is started)
To jump, of course, is to jump up and down from the ground. The next thing to consider is continuous animation.
That’s kind of how it feels…
// Tama.vue
jump (height) {
this.dy = -height
// Wait for the last animation to end
this.dy = 0
}
Copy the code
Use timer to achieve continuous animation
I think about it, there are two ways to wait:
- Simply wait with a timer
- Listen for the transitionEnd event
Although using 2 is stable, the code structure can be quite painful with multiple animations, so I’ll stick with 1 this time.
// Tama.vue
jump (height) {
this.dy = -height
this.easing = 'ease-out'
window.setTimeout(() = > {
this.dy = 0
this.easing = 'ease-in'
}, this.duration)
}
Copy the code
When easing is specified, it feels like a cloud when you jump. And you’re going to get back to where you were.
Implement continuous animation with async/await
In the old days, if we wanted to do complex animation, it was really… In one word: vomiting blood.
β Callback Hell β warning.
If you have to do three or four consecutive animations, you will know what it means to be uncomfortable.
To get rid of callback hell, use async/await instead. Having said that, in fact, there is nothing special to do, just the timer promise.
// src/core/Time.js
export default {
/** * Promise waits for a specified time *@param {Number} Ms Wait time *@return {Promise} Resolve */ after the specified time
wait (ms) {
return new Promise(resolve= > {
window.setTimeout(resolve, ms)
})
}
}
Copy the code
For those of you who haven’t seen it written like this before, it might be a little hard to understand, but once the timer promise is made, you can control the wait time like this.
console.log('This message shows')
await Time.wait(2000) // Wait 2 seconds here
console.log('This message was displayed 2 seconds later.')
Copy the code
This article will not say Promise or say async/await, so if you remember how to use it, you will have no problem.
With time.js, the bloody code looks something like this:
// Tama.vue
<script>
import Time from '@/core/Time'
export default{...async jump (height) {
this.dy = -height
this.easing = 'ease-out'
await Time.wait(this.duration)
this.dy = 0
this.easing = 'ease-in'
await Time.wait(this.duration)
}
...
}
Copy the code
Animation abstraction and encapsulation
In this way, more than 3 animations can be combined and executed consecutively. Now that we’re at this point, let’s wrap it up like an animation library.
Encapsulate it Tween style
In the previous example, the following two steps frequently manipulate the animation frame:
- Change variables in data frequently
- with
Time.wait
Wait for the animation to end
Here’s another way to pull it out
Tama.vue
methods: {
async tween (props, duration = 1000) {
Object.assign(this.$data, props)
this.$data.duration = duration
await Time.wait(duration)
},
async jump (height) {
await this.tween({ dy: -height, easing: 'ease-out' }, 1000)
await this.tween({ dy: 0.easing: 'ease-in' }, 1000)}}Copy the code
$data = object. assign (props); / / this.$data = object. assign (props); Wait to wait duration milliseconds. If you use this method when calling, the code will be much simpler.
Encapsulation of complex animations
Once you’ve encapsulated the Tween method, it’s easy to combine multiple animations, so let me refine the jump code again.
// Tama.vue
async jump (height = 200, duration = 2500) {
await this.tween({ dScaleY: 0.8.easing: 'ease' }, duration * 0.1)
await this.tween({ dy: -height, dScaleY: 1.1.easing: 'ease-out' }, duration * 0.35)
await this.tween({ dy: 0.dScaleY: 1.2.easing: 'ease-in' }, duration * 0.35)
await this.tween({ dScaleY: 0.7.easing: 'ease' }, duration * 0.1)
await this.tween({ dScaleY: 1.0.easing: 'ease' }, duration * 0.1)}Copy the code
Before the jump with a lingering action, when the jump stretch the body, even if only a picture, you can do piong Piong like pudding very cute action. π
So here, to summarize, post all the code in one go. In addition, in addition to jump, the walk method is also written.
// Tama.vue
<template>
<img class="tama-root" src="/img/tama.svg" alt="Table temp agistic code"
:style="{ transform: `translate(${x + dx}px, ${y + dy}px) scale(${scaleX * dScaleX}, ${scaleY * dScaleY}) rotate(${rotate + dRotate}deg)`, transition: `transform ${duration}ms ${easing}` }"
@click="jump(200)"
>
</template>
<style lang="scss" scoped>
.tama-root {
position: absolute;
left: 0;
top: 0;
margin: -300px auto auto -90px;
transform-origin: 90px 100%;
will-change: transform;
}
</style>
<script>
import Time from '@/core/Time'
export default {
name: 'Tama'.props: {
x: { type: Number.default: 200 },
y: { type: Number.default: 100 },
scaleX: { type: Number.default: 1.0 },
scaleY: { type: Number.default: 1.0 },
rotate: { type: Number.default: 0 }
},
data () {
return {
dx: 0.dy: 0.dScaleX: 1.0.dScaleY: 1.0.dRotate: 0.duration: 1000.easing: 'ease'}},methods: {
async tween (props = {}, duration = 1000) {
Object.assign(this.$data, props)
this.$data.duration = duration
await Time.wait(duration)
},
async jump (height = 200, duration = 2500) {
await this.tween({ dScaleY: 0.8.easing: 'ease' }, duration * 0.1)
await this.tween({ dy: -height, dScaleY: 1.1.easing: 'ease-out' }, duration * 0.35)
await this.tween({ dy: 0.dScale: 1.2.easing: 'ease-in' }, duration * 0.35)
await this.tween({ dScaleY: 0.7.easing: 'ease' }, duration * 0.1)
await this.tween({ dScaleY: 1.0.easing: 'ease' }, duration * 0.1)},async walk (step = 100, duration = 500) {
await this.to({ dRotate: 10.dScaleY: 0.8.easing: 'ease' }, duration * 0.2)
await this.to({ dx: this.dx + step, dy: -step * 0.2.dRotate: -5.dScaleY: 1.1.easing: 'cubic - the bezier (. 04,. 67,. 52, 1)' }, duration * 0.7)
await this.to({ dy: 0.dRotate: 0.dScaleY: 1.easing: 'ease' }, duration * 0.1)}}}</script>
Copy the code
Combination of animation
At this point, you can call abstracted, complex combinations of several animations called jump and walk methods. Finally, use these methods to compose more complex animations.
Add a button to app. vue. Click this button to add a continuous animation to tama Sang by combining the jump and walk methods.
// App.vue
<template>
<div id="app">
<button @click="play">Play</button>
<tama ref="tama" :x="100" :y="300" :scaleX="0.5" :scaleY="0.5"></tama>
</div>
</template>
Copy the code
Click the button to play something like this:
// App.vue
async play () {
const tama = this.$refs.tama
await tama.jump(100.1500)
await tama.walk(100.1200)
await tama.walk(60.600)
await tama.walk(40.400)
await tama.jump(200.2500)}Copy the code
Take a little hop -> take three steps -> finish with a big jump. This is a sequence of actions that can be represented in such a simple way. This time, there is only Tama SAN alone, but if we have a few more well-assembled characters, we should be able to combine them into complex movements, just like in the game.
conclusion
- The CSS transform coordinate is used as a parameter in the Vue. You can easily configure the position, size and Angle of SVG.
- Using the CSS Transition, you can animate positions, sizes, and angles.
- With async/await, it feels like the Tween library and very complex animations can be easily controlled.
- It’s easy to use when you start sizing.
- Vue basic operations are not introduced, do not understand when appropriate to refer to Vue introductory articles and so on.
- I have also written a class article before, one is to use Vue and SVG, do a shooting game “< cat π± fish π attack π> code commentary”, that is also used
Tama mulberry
The second is “Using the basic functions of Vue and Firebase to create a smooth personal website code explanation”, which is the same animation as this article.
The translator to remember
Animation looks good, the article is very detailed, basically as long as a little Vue, you can easily control. Writing code synchronously is also very cool, but after 9102 years of async/await it is a bit… This article was transferred from Qiita, a Japanese technology website, so there will be some Japanese text, which has been approved by the original author, and then I will see the opportunity to continue to translate others. And Tama sang is cute.
The original address qiita.com/yuneco/item…