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在下面的演示中演示了这一点,它结合了定时和交互驱动的状态变化: