过渡状态

Vue 的过渡系统提供了很多简便方法,可以在进入、离开时,以及对列表进行动画,但是对于数据变化的动画要如何处理呢?比如:

所有以上这些要么是存储为原始数字,要么可以转化为数字。一旦我们实现这步,就可以结合 Vue 的响应式和组件系统,使用第三方库补充中间状态(tween state),以对这些状态变化进行动画。

使用 watcher 对状态进行动画(Animating State with Watchers)

watcher 可以观察到从任何数值属性到另一个属性的变化,然后进行动画。这一抽象听起来很复杂,所以让我们深入一个使用 Tween.js 的例子:

<script src="https://unpkg.com/tween.js@16.3.4"></script>
<div id="animated-number-demo">
<input v-model.number="number" type="number" step="20">
<p>{{ animatedNumber }}</p>
</div>
new Vue({
el: '#animated-number-demo',
data: {
number: 0,
animatedNumber: 0
},
watch: {
number: function(newValue, oldValue) {
var vm = this
function animate () {
if (TWEEN.update()) {
requestAnimationFrame(animate)
}
}
new TWEEN.Tween({ tweeningNumber: oldValue })
.easing(TWEEN.Easing.Quadratic.Out)
.to({ tweeningNumber: newValue }, 500)
.onUpdate(function () {
vm.animatedNumber = this.tweeningNumber.toFixed(0)
})
.start()
animate()
}
}
})

{{ animatedNumber }}

当更新数值时,输入框下方就会对数值的更改进行动画。这是一个不错的 demo 示例,但是,对于不能直接存储为数字的值,比如有效的 CSS 颜色值?以下是我们如何通过添加 Color.js 来实现对非数值进行动画:

<script src="https://unpkg.com/tween.js@16.3.4"></script>
<script src="https://unpkg.com/color-js@1.0.3/color.js"></script>
<div id="example-7">
<input
v-model="colorQuery"
v-on:keyup.enter="updateColor"
placeholder="Enter a color"
>
<button v-on:click="updateColor">Update</button>
<p>Preview:</p>
<span
v-bind:style="{ backgroundColor: tweenedCSSColor }"
class="example-7-color-preview"
></span>
<p>{{ tweenedCSSColor }}</p>
</div>
var Color = net.brehaut.Color
new Vue({
el: '#example-7',
data: {
colorQuery: '',
color: {
red: 0,
green: 0,
blue: 0,
alpha: 1
},
tweenedColor: {}
},
created: function () {
this.tweenedColor = Object.assign({}, this.color)
},
watch: {
color: function () {
function animate () {
if (TWEEN.update()) {
requestAnimationFrame(animate)
}
}
new TWEEN.Tween(this.tweenedColor)
.to(this.color, 750)
.start()
animate()
}
},
computed: {
tweenedCSSColor: function () {
return new Color({
red: this.tweenedColor.red,
green: this.tweenedColor.green,
blue: this.tweenedColor.blue,
alpha: this.tweenedColor.alpha
}).toCSS()
}
},
methods: {
updateColor: function () {
this.color = new Color(this.colorQuery).toRGB()
this.colorQuery = ''
}
}
})
.example-7-color-preview {
display: inline-block;
width: 50px;
height: 50px;
}

Preview:

{{ tweenedCSSColor }}

动态状态过渡(Dynamic State Transitions)

就像 Vue 的过渡组件那样,动态数据所支撑的状态的过渡也可以实时更新,这对于制作原型十分有用!即使是一个简单的 SVG 多边形,在操作一些变量之后,也可是实现很多难以想象的效果。

See this fiddle for the complete code behind the above demo.

通过组件组织过渡(Organizing Transitions into Components)

管理太多的状态过渡,会快速增加 Vue 实例或者组件的复杂性。幸运的是,许多动画可以提取到专用的子组件中。让我们用前面的整数动画来举例:

<script src="https://unpkg.com/tween.js@16.3.4"></script>
<div id="example-8">
<input v-model.number="firstNumber" type="number" step="20"> +
<input v-model.number="secondNumber" type="number" step="20"> =
{{ result }}
<p>
<animated-integer v-bind:value="firstNumber"></animated-integer> +
<animated-integer v-bind:value="secondNumber"></animated-integer> =
<animated-integer v-bind:value="result"></animated-integer>
</p>
</div>
// 在我们的应用程序中,所有的整数动画,
// 现在都可以复用这种复杂的补间动画逻辑。
// 通过对组件配置更多的动态过渡策略
// 和复杂过渡策略,
// 可以使我们的界面十分清晰
Vue.component('animated-integer', {
template: '<span>{{ tweeningValue }}</span>',
props: {
value: {
type: Number,
required: true
}
},
data: function () {
return {
tweeningValue: 0
}
},
watch: {
value: function (newValue, oldValue) {
this.tween(oldValue, newValue)
}
},
mounted: function () {
this.tween(0, this.value)
},
methods: {
tween: function (startValue, endValue) {
var vm = this
function animate () {
if (TWEEN.update()) {
requestAnimationFrame(animate)
}
}
new TWEEN.Tween({ tweeningValue: startValue })
.to({ tweeningValue: endValue }, 500)
.onUpdate(function () {
vm.tweeningValue = this.tweeningValue.toFixed(0)
})
.start()
animate()
}
}
})
// 现在,可以将所有的动画复杂度,从 Vue 主实例中移除!
new Vue({
el: '#example-8',
data: {
firstNumber: 20,
secondNumber: 40
},
computed: {
result: function () {
return this.firstNumber + this.secondNumber
}
}
})
+ = {{ result }}

+ =

在子组件中,我们可以使用本页面所涵盖的所有过渡策略进行组合,再通过 Vue 提供的内置过渡系统 。将这些结合在一起,对于要实现的动画效果的限制很少。

Bringing Designs to Life

To animate, by one definition, means to bring to life. Unfortunately, when designers create icons, logos, and mascots, they’re usually delivered as images or static SVGs. So although GitHub’s octocat, Twitter’s bird, and many other logos resemble living creatures, they don’t really seem alive.

Vue can help. Since SVGs are just data, we only need examples of what these creatures look like when excited, thinking, or alarmed. Then Vue can help transition between these states, making your welcome pages, loading indicators, and notifications more emotionally compelling.

Sarah Drasner demonstrates this in the demo below, using a combination of timed and interactivity-driven state changes:

See the Pen Vue-controlled Wall-E by Sarah Drasner (@sdras) on CodePen.


原文:https://vuejs.org/v2/guide/transitioning-state.html