CSS 动画一站式指南( 四 )


  • 整个打字过程存在两个动画,一个是打字器自增宽度 , 一个是光标闪烁
  • 整个打字过程一闪一闪地完成,根据其断断续续的特点可判断该动画为逐帧动画
  • 这里用 CSS 简单实现了一个自动打字器,在线源码和演示 。
    2. CSS 动画综合实践(太空舱)2.1 太空舱动画介绍先简单介绍一下这个动画的一些背景:
    • 用户点击中间的抽奖按钮后会展示抽奖动画,然后展示将要前进的步数,小人会在跑道上跑动到相应的位置,到达此次终点后,小人展示停止动画并且显示中奖结果 。
    • 用户还可以通过长按中奖按钮触发显示五连抽和十连抽 , 当点击五连抽时,首先会展示抽奖动画,然后展示将要前进的步数,小人会在跑道上瞬间移动到相应的位置,然后展示停止的动画 , 紧接着展示中奖动画 。十连抽的过程和五连抽相同 。
    2.2 太空舱动画实现流程整体流程
    大体思路是将各个功能封装为类,并且控制每个类实现的功能较?。?这样可以更大程度地实现类的复用 。像下面介绍的Animate CSS这个动画库也是封装了很多类,想要什么效果直接引用即可,这里也是同理 。并在此基础上定义了一些函数对跑动等功能进行了封装,整体流程如下图所示 。
    CSS 动画一站式指南

    文章插图
    结合上图对太空舱动画中的一些点做一些简单的说明 。
    跑动的实现
    通过关键帧动画,将各个方向相邻两格之间的跑动封装为一个类 。每一帧代表跑动的姿态,并且每一帧通过 translate 向前进的方向移动,最后一帧刚好到达下一格 。
    以向南方向的跑动为例 。
    • 向南奔跑的类
    @translateSouthX@translateSouthY代表向南每两格 X 和 Y 方向的距离,.run-south-animation是一个mixin ,代表向南跑动的动画 。
    @import "./animation.less";@translateSouthX: -25px;@translateSouthY: 13.5px;// 向南方向跑动.run-south {background: url("...");background-size: 1680px 255px;.run-south-animation(@translateSouthX, @translateSouthY);}
    • 向南奔跑的动画
    .run-south-animation这个mixin是向南奔跑动画的实现,注意animation-timing-function
    的值要设置为steps(1)  , 因为这里每两帧之间不需要补间动画 。forwards表示最后的状态保持为动画结束时的状态 。animation-iteration-count的值为 1 表示动画只执行一次不需要重复,因为这里是为了封装一个移动一格的动画,每次使用这个封装好的类时只应该跑动一格 。
    关键帧runSouth中,经过多次测试最终选择了使用 28 帧,因为在此帧数下,动画较为流畅,图片的大小也可以接受 。在关键帧动画中 , 帧数的选取至关重要,要根据具体的需求反复测试,太多或太少都不合适 。
    @animationDuration: .7s// 向南奔跑动画.run-south-animation(@translateX, @translateY) {animation: runSouth @animationDuration forwards;animation-iteration-count: 1;animation-timing-function: steps(1);@keyframes runSouth {0% {transform: translate(0, 0);background-position: 0px -2*(@singleAstronautWidth+@verticalInterval);}...50.4% {transform: translate(@translateX / 28 * 14, @translateY / 28 * 14);background-position: -840px -2*(@singleAstronautWidth+@verticalInterval);}...100% {transform: translate(@translateX / 28 * 28, @translateY / 28 * 28);background-position: -1680px -2*(@singleAstronautWidth+@verticalInterval);}}}如何再次触发跑动动画
    当第一次将跑动的类(假设向南)赋予展示小人的元素时小人可以正常跑动,但是如果紧接着再将这个类赋予这个元素时,即使组件中的 state 改变了,也不会触发小人继续向南跑动了 。
    为了验证这一点,写了一个小 demo,如下代码所示,在 3 s 后改变 state 中的 cls 和 doc , 由于 cls 没有发生变化 , 即使 doc 发生了变化,也不会触发first类中的动画重新执行 , 在线源码和演示 。
    class App extends React.Component {state = {cls: 'first',doc: 'hello hello'}componentDidMount() {setTimeout(() => {this.setState({cls: 'first',doc: 'world world'})}, 3000)}render() {return <div><h1 className={this.state.cls}>{this.state.doc}</h1></div>;}}ReactDOM.render(<App />, document.getElementById("root"));body {height: 100vh;margin: 0;display: grid;place-items: center;max-width: 250px;margin: 0 auto;}.first {animation: myfirst 2s linear both;animation-iteration-count: 1;}@keyframes myfirst{from {background: red;}to {background: yellow;}}

    推荐阅读