Animations

1. Bezier curve 贝塞尔曲线

1. 什么是贝塞尔曲线?

贝塞尔曲线被用于在计算机图形学中绘制图形,或者用在CSS动画中, 或者很多其他地方。
贝塞尔曲线由控制点构成, 有以下几个特点:

  • 控制点并不都在曲线上。
  • 曲线的阶等于点的数目减去一个。
    【对于两点,则是一个线性曲线(一条直线),三点-二次曲线(抛物线),四点-三次曲线。】
  • 曲线总是在控制点的凸包内。

2. 如何计算贝塞尔曲线?

假设有控制点:P1 = (x1, y1) P2 = (x2, y2) P3 = (x3, y3) P4 = (x4, y4)
曲线的坐标取决于最后的方程式, 参数t[0, 1]之间。

  • 假如有两个点,则公式是:
    图片描述
  • 假如有三个点,则公式是:
    图片描述
  • 假如有四个点,则公式是:
    图片描述

根据这个公式,我们就可以计算x和y的坐标值了,以三个点为例:
图片描述
图片描述

假设这三个点的坐标是:(0,0), (0.5, 1) (1, 0)
图片描述
图片描述

所以这时当t的值,从01变化时,我们就可以根据上面的方程式算是对应的(x, y)坐标,再将这些坐标连成线,就画成了贝塞尔曲线。
t = 0, (0, 0)
t = 0.2, (0.2, 0.36)
t = 0.4, (0.4, 0.64)
t = 0.6, (0.6, 0.84)
t = 0.8, (0.8, 0.96)
t = 1, (1, 1)

2. CSS Animations

我们可以使用CSS3提供的transition来实现动画,而不借助Javascript的帮助.
CSS transition的想法非常简单,就是我们来描述一个属性以及这个属性将如何变化,当属性改变时,浏览器绘制动画过程。
CSS transition有四个属性:
transition-property 定义属性名称
transition-duration 定义动画持续时间
transition-timing-function 通过函数的方式来描述动画的执行过程
transition-delay 定义动画的延迟时间
当然transition的属性也可以简写成:transition:property duration timing-function delay

transition-property 不是所有的属性可以做成动画,可以的属性见这里https://www.w3.org/TR/css-tra...
如果这样定义:transition-property: all意味着要把所有属性做成动画.

transition-duration 持续时间需要使用ms或者s为单位。
transition-delay 定义延迟的时间
如果这样定义: transition-delay: 1s 动画在1s后开始进行
如果这样定义: transition-delay: -1s, 当delay是负值时, 则会减少相应的动画持续时间. 因为这时延迟执行就变成了超前执行。
transition-timing-function 描述动画的执行过程

1. 贝塞尔曲线

最常用的就是贝塞尔曲线了cubic-bezier(x1, y1, x2, y2)
执行CSS动画的贝塞尔曲线是三阶贝塞尔, 有四个控制点:
第一个点是: P1(0, 0)
最后第一个点是: P4(1, 1)
所以我们只需要定义中间的两个点: P2(x1, y1) P3(x2, y2)
所以计算曲面上点坐标的公式就是:
图片描述
图片描述

由于x1 = 0, x4 = 1, 所以简化一下就是:
图片描述

由于y1 = 0, x4 = 1, 所以简化一下就是:
图片描述

假定中间两个点的左边是: (0, 0.5) (0.5 ,1.0)
那么对应的公式就变为:
图片描述
图片描述

t的范围又是[0, 1], 所以我们就可以给定t不同的值,然后画出对应的曲线。

其中已经有几个内置的贝塞尔曲线可以用了,
linear cubic-bezier(0, 0, 1, 1)
ease cubic-bezier(0.25, 0.1, 0.25, 1.0)
ease-in cubic-bezier(0.42, 0, 1.0, 1.0)
ease-out` cubic-bezier(0, 0, 0.58, 1.0)
ease-in-out cubic-bezier(0.42, 0, 0.58, 1.0)

贝塞尔曲线不仅可以实现平滑的曲线,还可以实现跳跃的曲线.
如果某个点的y坐标出现了负值或者很大值时,贝塞尔曲线就可以跳的非常低或者非常高。
比如: transition: left 5s cubic-bezier(.5, -1, .5, 2);

2. Steps函数

steps(number, start/end)定时函数可以让动画一步一步的执行.
第一个参数定义步数
第二个参数如果为start, 意味着在动画开始的时候, 就要立即执行第一步.
如果为end, 意味着不在开始的时候执行,而且每一秒结束的时候执行.
step-start效果等用于steps(1, start).
step-end效果等用于steps(1, end).

3. transitionend事件

当CSS的动画结束时,会触发transitionend事件.
通常用来在动画完成后做些操作,或者合并动画效果.

    boat.onclick = function() {
      let times = 1;

      function go() {
        if (times % 2) {
          // swim to the right
          boat.classList.remove('back');
          boat.style.marginLeft = 100 * times + 200 + 'px';
        } else {
          // swim to the left
          boat.classList.add('back');
          boat.style.marginLeft = 100 * times - 200 + 'px';
        }
      }
      go();
      boat.addEventListener('transitionend', function() {
        times++;
        go();
      });
    };

4. Keyframes

语法: @keyframes animationname {keyframes-selector {css-styles;}}
animationname 必需, 定义动画的名称
keyframes-selector 必需, 定义动画时长的百分比.
合法值: 0~100%, from{ } 等价于0%, to{ }等价于100%
0%是动画开始的时间, 100%是动画结束的时间.
css-styles必需, 定义一个或多个CSS样式属性.

定义好@keyframes规则后,就可以配合animation属性来一起创建动画了.
举个栗子:

    .zorro {
      width: 50px;
      padding: 20px;
      text-align: center;
      background: gold;
      position: relative;
      animation: zorro 1s ease-in 0s 6 alternate;
    }
    @keyframes zorro {
        from {
          top: 0px;
          left: 0px;
        }
        33% {
          top: 0px;
          left: 150px;
        }      
        66% {
          top: 120px;
          left:0px;
        }            
        to {
          top: 120px;
          left: 150px;
        }
    }

from等价于0%, to等价于100%,中间可以定义其他百分比的动画时长.

3. Javascript Animations

JS可以处理一些CSS不能处理的动画.

1. setInterval

最简单的一个方式就是使用setInterval, 通过设定一定的间隔,然后在相应间隔做元素属性的变化, 在一段时间后, clearInterval, 这样就可以做成一个动画了.

   train.onclick = function() {
      let start = Date.now();
      let timer = setInterval(function() {
          let timePassed = Date.now() - start;
          train.style.left = timePassed / 5 + 'px';
          if (timePassed > 2000) clearInterval(timer);
      }, 20);
    }

我们定义一辆火车, 然后每隔20ms, 让火车动一下, 运动了2s后, 停止火车, 这样就形成了一个匀称运动的动画.


肾导
1.7k 声望105 粉丝

渐渐成熟的前端工程师。


引用和评论

0 条评论