Skip to content

Commit 270866f

Browse files
chrisvfritzyyx990803
authored andcommitted
update transitioning state guide with dynamic example
1 parent e144d69 commit 270866f

File tree

1 file changed

+144
-7
lines changed

1 file changed

+144
-7
lines changed

src/guide/transitioning-state.md

Lines changed: 144 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
---
2-
title: State Transitions
2+
title: Transitioning State
33
type: guide
44
order: 12
55
---
66

7-
Vue's transition system offers many simple ways to animate entering and leaving, but what about when the data behind your view simply changes? This data is often used to display:
7+
Vue's transition system offers many simple ways to animate entering, leaving, and lists, but what about animating your data itself? For example:
88

99
- numbers and calculations
10+
- colors displayed
1011
- the positions of SVG nodes
1112
- the sizes and other properties of elements
12-
- colors displayed
1313

1414
All of these are either already stored as raw numbers or can be converted into numbers. Once we do that, we can animate these state changes using 3rd-party libraries to tween state, in combination with Vue's reactivity and component systems.
1515

@@ -20,15 +20,15 @@ Watchers allow us to animate changes of any numerical property into another prop
2020
``` html
2121
<script src="https://npmcdn.com/[email protected]"></script>
2222

23-
<div id="example-6">
23+
<div id="animated-number-demo">
2424
<input v-model.number="number" type="number">
2525
<p>{{ animatedNumber }}</p>
2626
</div>
2727
```
2828

2929
``` js
3030
new Vue({
31-
el: '#example-6',
31+
el: '#animated-number-demo',
3232
data: {
3333
number: 0,
3434
animatedNumber: 0
@@ -55,13 +55,13 @@ new Vue({
5555

5656
{% raw %}
5757
<script src="https://npmcdn.com/[email protected]"></script>
58-
<div id="example-6" class="demo">
58+
<div id="animated-number-demo" class="demo">
5959
<input v-model.number="number" type="number">
6060
<p>{{ animatedNumber }}</p>
6161
</div>
6262
<script>
6363
new Vue({
64-
el: '#example-6',
64+
el: '#animated-number-demo',
6565
data: {
6666
number: 0,
6767
animatedNumber: 0
@@ -239,6 +239,143 @@ new Vue({
239239
</style>
240240
{% endraw %}
241241

242+
## Dynamic State Transitions
243+
244+
Just as with Vue's transition components, the data backing state transitions can be updated in real time, which is especially useful for prototyping! Even using a simple SVG polygon, you can achieve many effects that would be difficult to conceive of until you've played with the variables a little.
245+
246+
{% raw %}
247+
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.5/TweenLite.min.js"></script>
248+
<div id="svg-polygon-demo" class="demo">
249+
<svg width="200" height="200" class="demo-svg">
250+
<polygon :points="points" class="demo-polygon"></polygon>
251+
<circle cx="100" cy="100" r="90" class="demo-circle"></circle>
252+
</svg>
253+
<label>Sides: {{ sides }}</label>
254+
<input
255+
class="demo-range-input"
256+
type="range"
257+
min="3"
258+
max="500"
259+
v-model.number="sides"
260+
>
261+
<label>Minimum Radius: {{ minRadius }}%</label>
262+
<input
263+
class="demo-range-input"
264+
type="range"
265+
min="0"
266+
max="90"
267+
v-model.number="minRadius"
268+
>
269+
<label>Update Interval: {{ updateInterval }} milliseconds</label>
270+
<input
271+
class="demo-range-input"
272+
type="range"
273+
min="10"
274+
max="2000"
275+
v-model.number="updateInterval"
276+
>
277+
</div>
278+
<script>
279+
new Vue({
280+
el: '#svg-polygon-demo',
281+
data: function () {
282+
var defaultSides = 10
283+
var stats = Array.apply(null, { length: defaultSides })
284+
.map(function () { return 100 })
285+
return {
286+
stats: stats,
287+
points: generatePoints(stats),
288+
sides: defaultSides,
289+
minRadius: 50,
290+
interval: null,
291+
updateInterval: 500
292+
}
293+
},
294+
watch: {
295+
sides: function (newSides, oldSides) {
296+
var sidesDifference = newSides - oldSides
297+
if (sidesDifference > 0) {
298+
for (var i = 1; i <= sidesDifference; i++) {
299+
this.stats.push(this.newRandomValue())
300+
}
301+
} else {
302+
var absoluteSidesDifference = Math.abs(sidesDifference)
303+
for (var i = 1; i <= absoluteSidesDifference; i++) {
304+
this.stats.shift()
305+
}
306+
}
307+
},
308+
stats: function (newStats) {
309+
TweenLite.to(
310+
this.$data,
311+
this.updateInterval / 1000,
312+
{ points: generatePoints(newStats) }
313+
)
314+
},
315+
updateInterval: function () {
316+
this.resetInterval()
317+
}
318+
},
319+
mounted: function () {
320+
this.resetInterval()
321+
},
322+
methods: {
323+
randomizeStats: function () {
324+
var vm = this
325+
this.stats = this.stats.map(function () {
326+
return vm.newRandomValue()
327+
})
328+
},
329+
newRandomValue: function () {
330+
return Math.ceil(this.minRadius + Math.random() * (100 - this.minRadius))
331+
},
332+
resetInterval: function () {
333+
var vm = this
334+
clearInterval(this.interval)
335+
this.randomizeStats()
336+
this.interval = setInterval(function () {
337+
vm.randomizeStats()
338+
}, this.updateInterval)
339+
}
340+
}
341+
})
342+
343+
function valueToPoint (value, index, total) {
344+
var x = 0
345+
var y = -value * 0.9
346+
var angle = Math.PI * 2 / total * index
347+
var cos = Math.cos(angle)
348+
var sin = Math.sin(angle)
349+
var tx = x * cos - y * sin + 100
350+
var ty = x * sin + y * cos + 100
351+
return { x: tx, y: ty }
352+
}
353+
354+
function generatePoints (stats) {
355+
var total = stats.length
356+
return stats.map(function (stat, index) {
357+
var point = valueToPoint(stat, index, total)
358+
return point.x + ',' + point.y
359+
}).join(' ')
360+
}
361+
</script>
362+
<style>
363+
.demo-svg { display: block; }
364+
.demo-polygon { fill: #41B883; }
365+
.demo-circle {
366+
fill: transparent;
367+
stroke: #35495E;
368+
}
369+
.demo-range-input {
370+
display: block;
371+
width: 100%;
372+
margin-bottom: 15px;
373+
}
374+
</style>
375+
{% endraw %}
376+
377+
See [this fiddle](https://jsfiddle.net/chrisvfritz/fbvusejy/) for the complete code behind the above demo.
378+
242379
## Organizing Transitions into Components
243380

244381
Managing many state transitions can quickly increase the complexity of a Vue instance or component. Fortunately, many animations can be extracted out into dedicated child components. Let's do this with the animated integer from our earlier example:

0 commit comments

Comments
 (0)