前端动画,css3,svg

316 阅读3分钟

css动画

动画的原理:

  1. 视觉暂留作用
  2. 画面逐渐变化

动画的作用

  1. 愉悦感
  2. 因其作用
  3. 操作进行反馈
  4. 掩饰(程序在后台加载)

动画类型

  • transition补间动画(中间的过程浏览器脑补起来)
  • keyframe关键帧动画(也是补间动画,但是有很多关键帧)
  • 逐帧动画

transition(补间动画)

transition 属性设置元素当过渡效果,是一个复合属性,包括四个简写属性:

  • transition-property:指定CSS属性的name,transition效果(默认值:all)
  • transition-duration(必须):过渡效果持续时间(不指定默认为0,不会有任何效果)
  • transition-timing-function:指定过渡效果的转速曲线(默认值:ease)
  • transition-delay:指定过渡延迟开始时间(默认为0)
/* 复合写法 */
/*transition: property duration timing-function delay;*/

        .container{
            width: 100px;
            height: 100px;
            background: red;
            /* 复合属性 */
            transition:width 1s ease 2s ,background 3s;
            /* transition: all 1s; */
            /* 采用以下分属性也是可以的 */
            /*transition-duration: 2s;
            transition-property: all;
            transition-timing-function: ease;
            transition-delay: 0s;*/
        }
        .container:hover{
            width: 800px;
            background:green;
        }

transition-timing-function属性指的是过渡的“缓动函数”,用来指定属性过渡时动画运动形式,值可以是关键字、贝塞尔曲线(bezier),默认值为ease 关键字:linear| ease| ease-in| ease-out| ease-in-out| 贝塞尔:cubic-bezier(n,n,n,n);

  • ease:开始和结束慢,中间快
  • linear:匀速
  • ease-in:开始慢,越来越快
  • ease-out:结束慢,越来越慢
  • ease-in-out:先加速后减速,与ease类似,但比ease幅度大
  • cubic-bezier(n,n,n,n)贝塞尔曲线中4个值随意调整,就会得到不同的效果
    .tra{
        width: 50px;
        height: 50px;
        display: block;
        background-color: lightcoral;
        transition: 1s cubic-bezier(.75,2.03,0,.14);
    }
    .tra:hover{
        border-radius: 50%;
        background-color: blue;
    }

事件回调:transition属性只有一个事件,那就是transitionend事件,它在过渡事件完成后触发

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
<style>
    #test{
        height: 60px;
        width: 60px;
        background-color: lightpink;
        transition: width 1.5s;
        font-size: 12px;
    }
    #test:hover{
        width: 250px;
    }
</style>
    </head>
    <body>
        <div id="test"></div>
    </body>
    <script>
        //监听 transitionend 事件
        test.addEventListener("transitionend", myFunction);
        // 回调函数
        function myFunction(e){
            e = e || event;
            test.innerHTML = "过渡结束,执行事件回调内容"
        }
    </script>
</html>

keyframes动画

  • 相当于多个补间动画
  • 与元素状态的变化无关
  • 定义更加灵活
        .container{
            width: 100px;
            height: 100px;
            background: red;
            animation: run 1s linear;
            /* animation-direction: reverse; */
            /* animation-fill-mode: forwards; */
            animation-iteration-count: infinite;
            /* animation-play-state: paused; */
        }
        @keyframes run{
            0%{
                width: 100px;
            }
            50%{
                width: 800px;
            }
            100%{
                width: 100px;
            }
        }
  • 先定义动画
  • 在调用定义好的动画
div {
   	/* 调用动画 */
       animation-name: 动画名称;
    	/* 持续时间 */
    	animation-duration: 持续时间;
}
@keyframes 动画名称 {
       0% {
           width: 100px;
       }
       100% {
           width: 200px
       }
}

 div {
            width: 100px;
            height: 100px;
            background-color: aquamarine;
            /* 动画名称 */
            animation-name: move;
            /* 持续时间 */
            animation-duration: 4s;
            /* 动画速度曲线 */
            animation-timing-function: ease;
            /* 动画开始时间 */
            animation-delay: 1s;
            /* 动画播放次数 */
            /* animation-iteration-count: 2; */
            /* 动画播放方向 */
            /* animation-direction: alternate; */
            /* 动画结束后状态 */
            animation-fill-mode: forwards;

 /* 复合属性 */
/* animation: 动画名称 持续时间 运动曲线 何时开始 播放次数 是否反方向 起始与结束状态 */
   animation: name duration timing-function delay iteration-count direction fill-mode

简写里面不包含 animation-paly-state 暂停动画 animation-paly-state: paused; 经常和鼠标经过等其他配合使用

svg 动画(CSS)(keyframes动画)

环形进度条

  <div>
    <svg width="440" height="440" viewbox="0 0 440 440">
          <circle cx="220" cy="220" r="170" stroke-width="50" stroke="#D1D3D7" fill="none"></circle>
      <circle
        class="circle"
        cx="220"
        cy="220"
        r="170"
        stroke-width="50"
        stroke="#00A5E0"
        fill="none"
        transform="matrix(0,-1,1,0,0,440)"
      />
    </svg>
  </div
   <style>
      .circle {
        animation: circle 5s linear infinite;
      }

      @keyframes circle {
        from {
          stroke-dasharray: 0 1069;
        }
        to {
          stroke-dasharray: 1069 0;
        }
      }
   </style>

LOGO 描边

    const path = document.getElementById('logo')
    const pathLen = path.getTotalLength()
     <style>
    .logo-path {
      fill: none;
      stroke: #333;
      stroke-width: 1;
      animation: taobao 5s linear infinite forwards;
    }
    @keyframes taobao {
      from {
        stroke-dasharray: 6885;
        stroke-dashoffset: 6885;
      }
      to {
        stroke-dasharray: 6885;
        stroke-dashoffset: 0;
      }
    }
     </style>


### 逐帧动画
- 每帧都是关键帧,中间没有补间过程
- 依然使用关键帧动画
- 属于关键帧动画中的一种特殊情况
- 适用于无法补间计算的动画
- 资源较大
- 使用steps()

```js
    animation-timing-function:steps(1);
    //中间不要加东西,每个区间就只有一个状态
    step是指定每个区间帧数

问题

CSS中动画实现的方式有几种

  • transition
  • keyframes(animation)

过渡动画和关键帧动画的区别

  • 过度动画需要有状态变化,关键帧动画不需要有状态变化
  • 关键帧动画能控制更精细

CSS动画的性能

  • 性能不坏
  • 部分情况下优于JS
  • 但JS可以做到更好
  • 部分高危属性,box-shadow等

svg 动画(SMIL)

SMIL 全称 Synchronized Multimedia Integration Language,它允许我们通过 HTML 标签实现动画效果,它可以用于:

  • 实现过渡动画
  • 实现补间动画
  • 动画颜色变换
  • 路径运动动画(CSS3无法实现)

SMIL 包含以下标签:

<set>
<animate>
<animateColor>
<animateTransform>
<animateMotion>

set 标签

实现属性的延迟设置

<svg width="400" height="400">
  <rect x="0" y="0" width="100" height="100" fill="red">
    <set attributeName="x" attributeType="XML" to="10" begin="1s" />
    <set attributeName="x" attributeType="XML" to="20" begin="2s" />
    <set attributeName="x" attributeType="XML" to="30" begin="3s" />
    <set attributeName="x" attributeType="XML" to="40" begin="4s" />
    <set attributeName="x" attributeType="XML" to="50" begin="5s" />
  </rect>
</svg>

animation 标签

移动的小球

<svg width="500" height="200" viewBox="0 0 500 200">
  <circle cx="0" cy="0" r="30" fill="blue" stroke="black" stroke-width="1">
    <animate attributeName="cx" from="0" to="200" dur="5s" repeatCount="indefinite" />
    <animate attributeName="cy" from="0" to="200" dur="5s" repeatCount="indefinite" />
  </circle>
</svg>

形状补间动画

<svg width="400" height="400">
  <polygon points="30 30 70 30 90 70 10 70" fill="#fcc" stroke="black">
    <animate attributeName="points" attributeType="XML" to="50 30 70 50 50 90 30 50" dur="5s" fill="freeze" repeatCount="1" />
  </polygon>
</svg>

animateMotion 标签

按 path 轨迹运动的正方形

<svg width="200" height="200" viewBox="0 0 200 200">
  <rect x="0" y="0" width="10" height="10" fill="red">
    <animateMotion
      path="M 10 10 L 110 10 L 110 110 L 10 110 Z"
      dur="5s"
      rotate="auto"
      fill="freeze"
      repeatCount="indefinite"
    />
  </rect>
  <path id="motion-path" d="M 10 10 L 110 10 L 110 110 L 10 110 Z" fill="none" stroke="green" />
</svg>

混合动画

<svg viewBox="0 0 200 200" width="200" height="200">
    <rect x="0" y="0" rx="0" ry="0" width="10" height="10" fill="red">
      <animateMotion
        id="forward-rect"
        path="M 10 10 L 110 10 L 110 110 L 10 110"
        dur="2s"
        rotate="0"
        fill="freeze"
        begin="0; backward-rect.end + 0.5s"
      />
      <animateMotion
        id="backward-rect"
        path="M 10 110 L 110 110 L 110 10 L 10 10"
        dur="2s"
        rotate="0"
        fill="freeze"
        begin="forward-rect.end + 0.5s"
      />
      <animate
        id="red-to-blue"
        attributeType="XML"
        attributeName="fill"
        begin="0; blue-to-red.end + 1s"
        from="red"
        to="blue"
        dur="2s"
        fill="freeze"
      />
      <animate
        id="blue-to-red"
        attributeType="XML"
        attributeName="fill"
        begin="red-to-blue.end + 1s"
        from="blue"
        to="red"
        dur="2s"
        fill="freeze"
      />
    </rect>
    <path d="M 10 10 L 110 10 L 110 110 L 10 110" fill="none" stroke-width="1" stroke="blue"/>
</svg>

点击变色或位移

<svg viewBox="0 0 200 200" width="200" height="200">
    <g id="rect1">
      <rect x="0" y="0" rx="0" ry="0" width="100" height="100" fill="red">
        <animate
          attributeType="XML"
          attributeName="fill"
          from="red"
          to="green"
          begin="rect1.click"
          dur="2s"
          fill="freeze"
        />
      </rect>
    </g>
    <animateTransform
      attributeType="XML"
      attributeName="transform"
      type="translate"
      from="0, 0"
      to="50, 50"
      begin="rect1.click"
      dur="2s"
      fill="freeze"
    />
    <rect x="0" y="100" width="100" height="100" fill="blue">
      <animate
        attributeType="XML"
        attributeName="fill"
        from="blue"
        to="green"
        begin="rect1.click"
        dur="2s"
        fill="freeze"
      />
    </rect>
</svg>

Loading 效果

   <div style="width:200px;height:200px">
      <svg viewBox="0 0 50 50">
        <circle
          cx="25"
          cy="25"
          r="22"
          fill="none"
          stroke-width="3"
          stroke="#3be6cb"
          stroke-dasharray="34"
          stroke-linecap="round"
        >
          <animateTransform
            attributeName="transform"
            type="rotate"
            from="0 25 25"
            to="360 25 25"
            dur="2s"
            repeatCount="indefinite"
          />
          <animate
            attributeName="stroke"
            values="#3be6cb;#02bcfe;#3be6cb"
            dur="4s"
            repeatCount="indefinite"
          />
        </circle>
        <circle
          cx="25"
          cy="25"
          r="12"
          fill="none"
          stroke-width="3"
          stroke="#02bcfe"
          stroke-dasharray="18.85"
          stroke-linecap="round"
        >
          <animateTransform
            attributeName="transform"
            type="rotate"
            values="360 25 25;0 25 25"
            dur="2s"
            repeatCount="indefinite"
          />
          <animate
            attributeName="stroke"
            values="#02bcfe;#3be6cb;#02bcfe"
            dur="4s"
            repeatCount="indefinite"
          />
        </circle>
      </svg>
    </div>

流星轨迹边框效果

 <div style="width:400px;height:400px;background-color:#333">
      <svg viewBox="0 0 400 400">
        <defs>
          <path
            id="fly-box-path"
            d="M5 5 L395 5 L395 395 L5 395 Z"
            fill="none"
          />
          <radialGradient
            id="radial-gradient"
            cx="50%"
            cy="50%"
            fx="100%"
            fy="50%"
            r="50%"
          >
            <stop offset="0%" stop-color="#fff" stop-opacity="1"></stop>
            <stop offset="100%" stop-color="#fff" stop-opacity="0"></stop>
          </radialGradient>
          <mask id="fly-box-mask1">
            <circle r="100" cx="0" cy="0" fill="white">
              <animateMotion
                dur="3s"
                path="M5 5 L395 5 L395 395 L5 395 Z"
                rotate="auto"
                repeatCount="indefinite"
              />
            </circle>
          </mask>
        </defs>
        <use
          href="#fly-box-path"
          stroke-width="1"
          stroke="#235fa7"
        />
        <use
          href="#fly-box-path"
          stroke-width="3"
          stroke="#4fd2dd"
          mask="url(#fly-box-mask1)"
        />
      </svg>
    </div>