Prague 21 Sept18
Freelance Dev & Instructor
Vue core team
๐โโ๏ธ โจ๏ธ ๐
Made with Nuxt!
I'm taking
my time
to appear...
Entering/Leaving the page (v-if, v-show, key)
Reordering (v-for)
.fade-in, .fade-out {
transition: opacity 300ms;
}
.fade-out {
opacity: 0;
}
.my-element {
animation: moving 1s infinite alternate;
}
@keyframes moving {
0% { transform: translateX(0); }
100% { transform: translateX(200px); }
}
๐ rotation, translation, scaling
๐ opacity, colours, etc
๐ Basic Transition
<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>
transition
animation
transition: opacity 1s;
0
1
animation: fade 1s;
0
1
.8
(keyframes)
How to go from one state to another
ย
Go from 10ย to 100 Bouncing outย in 1 second
10: initial value
100: target value
Bouncing out: Easing
1s: duration
๐ Easing graph
Inspired by easings.net
Go to 100ย quickly and no oscillation
100: target value
quickly: high stiffness
no oscillation: low damping
๐ Motion graph
(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 ๐ฑ
Originally from docs
by @chrisvfritz
๐ Polygon
<Tweezing
:to="stats"
:duration="updateInterval"
:easing="easing"
>
<polygon
slot-scope="pointsArray"
:points="transformToPoints(pointsArray)"
></polygon>
</Tweezing>
Focus on how the state maps to your components, not on how to keep everything in sync
Using the scroll instead of time as input
๐ Easing with mouse
<Tweezing
:to="1" tween="custom"
:time="mouseYPer"
>
<div slot-scope="value">
<pre>{{ mouseYPer }}%</pre>
<div class="ball" :style="ballStyle(value)">
</div>
</div>
</Tweezing>
Watch target value โก๏ธ create Tween
Provide tweened value with a scoped slot
this.rotation // 10
this.rotation = 220
// triggers a new tweening
import {
Tweezing,
tweenjsHelper,
} from 'vue-tweezing'
import TWEEN from '@tweenjs/tween.js'
Vue.use(Tweezing, {
tweenjs: tweenjsHelper(TWEEN),
})
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()
}
}
๐ Plot
<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>
Originally from docs
by @chrisvfritz
๐ Sudoku
<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>
<Music
src="meatball-parade.mp3"
:rate="rate"
/>
<Motion :value="rate" :spring="springConfig">
<Music
scoped-slot="{ value }"
src="meatball-parade.mp3"
:rate="value"
/>
</Motion>
<Renderer :width="width" :height="height">
<Scene>
<Camera :position="camPos"/>
<AmbientLight/>
<SpotLight :position="lightPosition"/>
<Cube
v-for="cube in cubes"
:key="cube.id"
:position="cube.position"
/>
<Ground/>
</Scene>
</Renderer>
<Motion v-for="(cube, i) in cubes"
:values="cube" :key="i"
>
<Cube
slot-scope="cube"
:position="cube.position"
/>
</Motion>
Browsers + GPU โฅ๏ธ Pure CSSย