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

State Animations with Vue

By Eduardo San Martin Morote

State Animations with Vue

Aah, animations. Moving things on the screen will either fascinate your users or make them close your app right away. Add no animations and your users will feel sometimes lost. Add too much and they will be disgusted. But, to make it harder, animations by themselves have to be configured just right to have a meaning. Speed, duration and the object being animated have to be set just right. Now, Vue already provides us with two nice components: transition and transition-group that are based on CSS animations. But what about the state? Numerical values that change and you want to animate. During my talk, I will explain what state transitions are, how they differ from CSS transitions, what are they used for and show some practical implementations. We will cover good and bad practices while we delight ourselves with some demos.

  • 1,475
Loading comments...

More from Eduardo San Martin Morote