State Animations

Amsterdam 16 Feb

GitHub icon
Twitter icon

Eduardo

San Martin Morote

Vue core team

Author of VueFire 2, VueMotion, VueTweezing

Vue 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

Limited to

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

State Animations

What is it?

How to go from one state to another

 

  • Boolean toggling
  • Easings
  • Physics 

Boolean state Class switching

👎 rotation, translation, scaling (unless linear easing)

👍 opacity, colours, etc

👉 Basic Transition

👌 with computed properties

computed: {
  checkoutButtonClasses () {
    return {
      // apply a transition on colour
      'is-disabled': this.cart.length > 0
    }
  }
}

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

  • 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

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>{{ value }}</pre>
    <div class="ball" :style="ballStyle(value)">
    </div>
  </div>
</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>

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!

Thanks! 🖖

GitHub icon
Made with Slides.com