• 前端实现动画效果的几种方式 九种


    原文链接: https://www.cnblogs.com/yalong/p/16385198.html

    一. Js实现

    代码如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <style type="text/css">
        #rect {
           200px;
          height: 200px;
          background: gray;
        }
      </style>
    </head>
    <body>
      <div id="rect"></div>
      <script>
        let elem = document.getElementById('rect');
        let left = 0;
        let timer = setInterval(function(){
          if(left + 200 < window.innerWidth){
            elem.style.marginLeft = left+'px';
            left ++;
          }else {
            clearInterval(timer);
          }
        }, 16);
      </script>
    </body>
    </html>
    
    

    存在的问题

    javascript 实现动画通常会导致页面频繁性重排重绘,消耗性能,一般应该在桌面端浏览器,在移动端上使用会有明显的卡顿。

    为什么是16ms

    上面例子中,我们设置的setInterval时间间隔是16ms
    一般认为人眼能辨识的流畅动画为每秒60帧,这里16ms比(1000ms/60)帧略小一些,但是一般可仍为该动画是流畅的。
    如果大于16ms, 比如设置成500ms, 会明显感觉的卡顿。
    在很多移动端动画性能优化时,一般使用16ms来进行节流处理连续触发的浏览器事件。
    例如对touchmove、scroll事件进行节流等, 通过这种方式减少持续事件的触发频率,可以大大提升动画的流畅性。

    二. CSS3 transition

    代码如下

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8"> 
    <title>菜鸟教程(runoob.com)</title>
    <style> 
    div {
         100px;
        height: 100px;
        background: red;
        transition: width 2s, height 2s, transform 2s;
    	transition-timing-function:linear;
    	transition-delay:1s;
    }
    
    div:hover {
         200px;
        height: 200px;
        transform: rotate(180deg);
    }
    </style>
    </head>
    <body>
    <p><b>注意:</b>该实例无法在 Internet Explorer 9 及更早 IE 版本上工作。</p>
    
    <div>鼠标移动到 div 元素上,1秒后 开始过渡效果。</div>
    </body>
    </html>
    

    transition是过度动画
    但是transition并不能实现独立的动画,只能在某个标签元素样式或状态改变时进行平滑的动画效果过渡,而不是马上改变

    三. CSS3 animation

    代码如下

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8"> 
    <title>菜鸟教程(runoob.com)</title>
    <style> 
    div
    {
    	100px;
    	height:100px;
    	background:red;
    	position:relative;
    	animation-name:myfirst;
    	animation-duration:5s;
    	animation-timing-function:linear;
    	animation-delay:2s;
    	animation-iteration-count:infinite;
    	animation-direction:alternate;
    	animation-play-state:running;
    	/* Safari and Chrome: */
    	-webkit-animation-name:myfirst;
    	-webkit-animation-duration:5s;
    	-webkit-animation-timing-function:linear;
    	-webkit-animation-delay:2s;
    	-webkit-animation-iteration-count:infinite;
    	-webkit-animation-direction:alternate;
    	-webkit-animation-play-state:running;
    }
    
    @keyframes myfirst
    {
    	0%   {background:red; left:0px; top:0px;}
    	25%  {background:yellow; left:200px; top:0px;}
    	50%  {background:blue; left:200px; top:200px;}
    	75%  {background:green; left:0px; top:200px;}
    	100% {background:red; left:0px; top:0px;}
    }
    
    @-webkit-keyframes myfirst /* Safari and Chrome */
    {
    	0%   {background:red; left:0px; top:0px;}
    	25%  {background:yellow; left:200px; top:0px;}
    	50%  {background:blue; left:200px; top:200px;}
    	75%  {background:green; left:0px; top:200px;}
    	100% {background:red; left:0px; top:0px;}
    }
    </style>
    </head>
    <body>
    
    <p><b>注意:</b> 该实例在 Internet Explorer 9 及更早 IE 版本是无效的。</p>
    
    <div></div>
    
    </body>
    </html>
    

    animation 算是真正意义上的CSS3动画。通过对关键帧和循环次数的控制,页面标签元素会根据设定好的样式改变进行平滑过渡
    而且关键帧状态的控制是通过百分比来控制的

    四. SVG

    代码如下

    <!DOCTYPE html>
    <html>
    <body>
    
    <p><b>Note:</b> This example only works in Firefox and Google Chrome.</p>
    
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
      <g transform="translate(100,100)">
        <text id="TextElement" x="0" y="0" style="font-family:Verdana;font-size:24"> It's SVG!
          <animateMotion path="M 0 0 L 100 100" dur="5s" fill="freeze" />
        </text>
      </g>
    </svg>
    
    </body>
    </html>
    

    SVG的教程看这里:https://www.runoob.com/svg/svg-tutorial.html

    SVG的一大优势是含有较为丰富的动画功能,原生绘制各种图形、滤镜和动画,并且能被js调用。html是对dom的渲染,那么svg就是对图形的渲染。

    但是,另一方面元素较多且复杂的动画使用svg渲染会比较慢,而且SVG格式的动画绘制方式必须让内容嵌入到HTML中使用

    CSS3的出现让svg的应用变得相对少了。

    五. Canvas

    代码如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <style>
      *{
        margin:0;
        padding:0;
      }
      </style>
    </head>
    <body>
      <canvas id="canvas" width="700" height="550"></canvas>
      <script type="text/javascript">
        let canvas = document.getElementById("canvas");
        let ctx = canvas.getContext("2d");
        let left = 0;
        let timer = setInterval(function(){
          ctx.clearRect(0,0,700,550);
          ctx.beginPath();
          ctx.fillStyle = "#ccc";
          ctx.fillRect(left,0,100,100);
          ctx.stroke();
          if(left>700){
            clearInterval(timer);
          }
          left += 1;
        },16);
      </script>
    </body>
    </html>
    

    Canvas 相关教程看这里: https://www.runoob.com/html/html5-canvas.html

    Canvas主要优势是可以应对页面中多个动画元素渲染较慢的情况,完全通过javascript来渲染控制动画的执行。可用于实现较复杂动画。

    六. requestAnimationFrame

    代码如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <style>
      #some-element-you-want-to-animate{
         100px;
        height: 100px;
        background: red;
      }
      </style>
    </head>
    <body>
      <div id="some-element-you-want-to-animate"></div>
      <script type="text/javascript">
        const element = document.getElementById('some-element-you-want-to-animate');
        let start = 0;
    
        function step() {
          element.style.transform = 'translateX(' + start + 'px)';
          start++
          if (start < 200) { // 在两秒后停止动画
            window.requestAnimationFrame(step);
          }
        }
        window.requestAnimationFrame(step);
      </script>
    </body>
    </html>
    

    requestAnimationFrame 相关资料看这里: https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame

    requestAnimationFrame是另一种Web API,原理与setTimeout和setInterval类似,都是通过javascript持续循环的方法调用来触发动画动作。

    但是requestAnimationFrame是浏览器针对动画专门优化形成的APi,在性能上比另两者要好。

    前面提到,大多数显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过这个频率用户体验也不会提升。

    因此,最平滑动画的最佳循环间隔是 1000ms/60 ,约16ms。这个循环间隔重绘的动画是最平滑的,因为这个速度最接近浏览器的最高限速。

    通常,我们将执行动画的每一步传到requestAnimationFrame中,在每次执行完后进行异步回调来连续触发动画效果。

    requestAnimationFrame只是将回调的方法传入到自身的参数中执行,而不是通过setInterval调用

    要知道,无论是setInterval()还是setTimeout()都不十分精确,

    因为它们传入的第二个参数,实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行时间。

    如果队列前面已经加入其他任务,那动画代码就要等前面的任务完成后再执行。

    七.GIF

    对于一些特别动画,代码如果不好实现,完全可以制作成GIF图的形式, 可以看下阿里云官网, 上面好几个动画都是gif制作的,效果也挺好的。

    比如下面这个GIF图

    八. 雪碧图

    类似下面这种图片,作为背景图片,改变图片位置,实现动画效果

    代码如下

     <!DOCTYPE html>
     <html>
         <head>
             <meta charset="utf-8">
             <title></title>
             <style>
                 
                 .box1{
                     height: 271px;
                      132px;
                     background-image: url(https://img2022.cnblogs.com/blog/872412/202206/872412-20220617113333620-46319996.png);
                     margin: 50px auto;
                     /* 应用动画   */
                     animation: walk 1s steps(4) infinite;
                 }
                 
                 @keyframes walk{
                     from{
                         background-position: 0 0;
                     }
                     to{
                         background-position:-528px 0;
                     }
                 }
                 
                 
             </style>
         </head>
         <body>
             
             <div class="box1">
                 
             </div>
             
         </body>
     </html>
    

    九. Video

    这个已经有点超越动画范畴了,可以说几乎任何效果都可以用video实现,根据实际需求,酌情使用,因为视频的加载还是有点慢的~

    性能优化

    上述是动画的几种实现方式,但是有时候还需要对动画的性能进行优化,找了一些不错的文章,可以参考

    前端动画性能优化

    无线性能优化

    前端性能优化系列 | 加载优化

  • 相关阅读:
    输出流对象
    1.2最简单的c++程序
    c++的初步认识
    理想程序员
    从字符数组中删除字符
    打印杨辉三角
    旋转数组
    找出1000以内的所有完数
    计算兔子的总数
    101-200有多少个素数?
  • 原文地址:https://www.cnblogs.com/yalong/p/16385198.html
Copyright © 2020-2023  润新知