Animations With Vue.js

Paris 29 June 18

GitHub icon
Twitter icon

Eduardo

San Martin Morote

Vue core team

VueFire, VueMotion, VueTweezing

Freelance, Instructor around Europe


GitHub icon

Demo

Made with Nuxt!

Animations are hard

Activity monitor

Animations should be fast

Hi there 👋

I'm taking

my time

to appear...

Animating when...

  • The user does something
  • We need user's attention
  • We want to make things fun

<Transition/> 

<Transition-group/>

Based on

  • v-if
  • v-show
  • key
  • v-for
:key
<transition name="fade" mode="out-in">
  <router-view :key="$route.fullPath"/>
</transition>

 trick

Using

CSS or

Javascript

Transition + Animate.css

👎 rotation, translation, scaling

👍 opacity, colours, etc

👉 Basic Transition

Transition + ANimate.css

<transition
  enter-active-class="animated slideInLeft"
  leave-active-class="animated slideOutRight fadeOut"
>
  <div v-if="on" key="onDiv">On</div>
  <div v-else>Off</div>
</transition>

Limited to

  • Elements appearing
  • Elements disappearing
  • Elements reordering
  • CSS properties

State Animations

What is it?

How to go from one state to another

 

  • Easings
  • Physics 

Easing

Go from 10 to 100 Bouncing out in 1 second

10: initial value

100: target value

Bouncing out: Easing

1s: duration

👉 Easing graph

SPRING

Go to 100 quickly and no oscillation

100: target value

quickly: high stiffness

no oscillation: low damping

👉 Motion graph

Easing

  • highly customisable
  • many existing easings
  • custom duration
  • easy to chain
  • playback control

Spring

  • only two parameters
  • always feels natural
  • handles interruptions/changes

Tween.js

(or any other tweening lib)

// setup the animation loop
// (do it somewhere, but only once)
function animate(time) {
  requestAnimationFrame(animate)
  TWEEN.update(time)
}
requestAnimationFrame(animate)

const container = { x: 0 } // Tween modifies this
const tween = new TWEEN.Tween(container)
  .to({ x: 300 }, 1000) // change to 300 in 1s
  .easing(TWEEN.Easing.Quadratic.Out)
  .onUpdate(() => {
    // container.x is updated
  })
  .start() // Start the tween immediately.

Necessary boilerplate to create one single tween 😱

Tweening with

Vue tweezing

Polygon example

Originally from docs

by @chrisvfritz

👉 Polygon

✨ Declarative Tweening

<Tweezing
  :to="stats"
  :duration="updateInterval"
  :easing="easing"
>
  <polygon
    slot-scope="pointsArray"
    :points="transformToPoints(pointsArray)"
  ></polygon>
</Tweezing>

Easings controlled by scroll/Mouse

Using the scroll instead of time as input

👉 Easing with mouse

✨ Declarative Tweening

<Tweezing
  :to="1" tween="custom"
  :time="mouseYPer"
>
  <div slot-scope="value">
    <pre>{{ mouseYPer }}%</pre>
    <div class="ball" :style="ballStyle(value)">
    </div>
  </div>
</Tweezing>

Tweezing component

  • Watch target value ➡️ create Tween

  • Provide tweened value with a scoped slot

this.rotation // 10
this.rotation = 220
// triggers a new tweening

Tween engines

import {
  Tweezing,
  tweenjsHelper,
} from 'vue-tweezing'
import TWEEN from '@tweenjs/tween.js'

Vue.use(Tweezing, {
  tweenjs: tweenjsHelper(TWEEN),
})

Tween.js

export function tweenjsHelper (TWEEN) {
  return function (value, end, opts) {
    const container = { value }
    // cancel previous tween
    return new TWEEN.Tween(container)
      .to({ value: end }, opts.duration)
      .interpolation(opts.interpolation || TWEEN.Interpolation.Linear)
      .easing(opts.easing || TWEEN.Easing.Quadratic.Out)
    // TODO should probably emit the name of the property too
    // default could be the name if only one value is provided
      .onStart(() => this.$emit('start'))
      .onUpdate(() => {
        opts.$setValue(container.value)
      })
      .onComplete(() => this.$emit('end'))
      .start()
  }
}

Tweezing

🗜< 1kb

Springs

with

vue motion

svg Chart

Codepen

by @sarah_edo

👉 Plot

✨ Declarative Spring

<Motion tag="g" :values="selectedValues">
  <template slot-scope="values">
    <g v-for="(y, i) in values" class="bars">
      <rect
        :x="i * 10 + 20"
        :y="getMax - y * 10"
        width="10"
        :height="y * 10"
      />
    </g>
  </template>
</Motion>

Lazy sudoku example

Originally from docs

by @chrisvfritz

👉 Sudoku

"Original"

with springs

✨ Declarative Spring

<Motion :values="positions" spring="wobbly">
  <template slot-scope="positions">
    <div v-for="cell in cells"
      :style="{\
        transform: `translate(\
          ${positions[cell.id].x}px,\
          ${positions[cell.id].y}px)\
      `}"
    >
      {{ cell.number }}
    </div>
  </template>
</Motion>

Bonus

🔈 Sounds

🙉

Getting started

⚠️ vue-motion and vue-tweezing are experimental

🗣Feedback is very welcome!

GitHub icon

Thanks! 🖖

GitHub icon
Made with Slides.com