13. State Transitions(状态转换)
状态转换
Vue的过渡系统提供了许多简单的方法来动画进入,离开和列表,但动画数据本身又如何呢?例如:
- 数字和计算
- 显示颜色
- SVG节点的位置
- 元素的大小和其他属性
所有这些都已经存储为原始数字或可以转换为数字。一旦我们这样做了,我们就可以使用第三方库对这些状态更改进行动画处理,以结合Vue的反应性和组件系统。
用观察者动画状态
观察者允许我们将任何数值属性的变化动画成另一个属性。这听起来可能听起来很复杂,所以我们来深入一个使用Tween.js的例子:
<script src="https://cdn.jsdelivr.net/npm/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()
}
}
})
当您更新号码时,更改会在输入下面显示动画。这使得一个很好的演示,但什么东西不是直接存储为一个数字,如任何有效的CSS颜色,例如?以下是我们如何通过添加Color.js来实现这一点:
<script src="https://cdn.jsdelivr.net/npm/tween.js@16.3.4"></script>
<script src="https://cdn.jsdelivr.net/npm/color-js@1.0.3"></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;
}
动态状态转换
与Vue的转换组件一样,数据支持状态转换可以实时更新,这对原型设计特别有用!即使使用简单的SVG多边形,也可以实现许多难以想象的效果,直到您稍稍使用变量。
请参阅此fiddle以获取上述演示背后的完整代码。
将转换组织成组件
管理许多状态转换可能会快速增加Vue实例或组件的复杂性。幸运的是,许多动画可以提取出专用的子组件。我们用前面例子的动画整数来做这件事:
<script src="https://cdn.jsdelivr.net/npm/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>
// This complex tweening logic can now be reused between
// any integers we may wish to animate in our application.
// Components also offer a clean interface for configuring
// more dynamic transitions and complex transition
// strategies.
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()
}
}
})
// All complexity has now been removed from the main Vue instance!
new Vue{
el: '#example-8',
data: {
firstNumber: 20,
secondNumber: 40
},
computed: {
result: function () {
return this.firstNumber + this.secondNumber
}
}
})
在子组件中,我们可以使用本页所涵盖的任何转换策略组合,以及Vue内置的转换系统提供的转换策略组合。一起,可以完成的事情几乎没有限制。
把设计代入生活
通过一个定义来制作动画,就可以实现生命。不幸的是,当设计师创建图标,标志和吉祥物时,他们通常以图像或静态SVG的形式提供。因此,虽然GitHub的octocat,Twitter的鸟和其他许多标识类似于生物,但它们看起来并不真实。
Vue可以提供帮助。由于SVG只是数据,我们只需要这些生物在兴奋,思考或警觉时看起来像什么的例子。然后,Vue可以帮助在这些状态之间切换,使您的欢迎页面,加载指示器和通知更加情感化。
Sarah Drasner在下面的演示中演示了这一点,它结合了定时和交互驱动的状态变化: