jQuery之模拟实现$().animate()(上)

栏目: jQuery · 发布时间: 1年前

来源: segmentfault.com

内容简介:根据上图实现除

本文转载自:https://segmentfault.com/a/1190000019618967,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有。

jQuery之模拟实现$().animate()(上)

jQuery之模拟实现$().animate()(上)

根据上图实现除 doAnimation 外的逻辑:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>jQuery之$().animate()的实现</title>
</head>
<body>
<script src="jQuery.js"></script>

  <div id="A" style="width:100px;height:50px;background-color: deeppink">这是A</div>

<script>
  //匿名函数自调用,下面好长好长的function就是$
  //也就是说$是一个function(){xxx}
  (function($) {

    window.$ = $;

  })(
    //这里也是匿名函数自调用
    //本质就是经过一系列操作得到chenQuery并作为参数$,赋值给window.$
    function() {
      //匹配ID
      let rquickExpr = /^(?:#([\w-]*))$/;
      //jQuery初始化
      function chenQuery(selector) {
        return new chenQuery.fn.init(selector);
      }

      //假设是在数据缓存中存取队列
      const Queue=[]

      //数据缓存
      const dataPriv={
        get:function (type) {
          if(type==='queue') return Queue
        },

      }

      const dequeue=function() {
        const Queue=dataPriv.get("queue")
        let fn = Queue.shift()
        //当单个动画结束后,执行下个动画
        const next = function() {
          dequeue();
        }

        if ( fn === "inprogress" ) {
          fn = Queue.shift();
        }

        if (fn) {
          Queue.unshift( "inprogress" );
          /*执行doAnimation方法,doAnimation(element, options,function() {firing = false;_fire();})*/
          /*fn的参数就是形参func*/
          /*func方法是用来通知上个动画结束,下个动画运行的重要function*/
          //func的作用是用来通知动画执行结束,并继续执行下一个动画
          const func=function() {
            next();
          }
          fn(func);
        }


      }

      //省略type
      const queue=function(element, options, callback, ) {
        //模仿从数据缓存中得到的队列,直接写Queue.push也行
        const Queue=dataPriv.get("queue")
        //向动画队列中添加doAnimation触发器
        Queue.push(function(func) {
          //doAnimation
          callback(element, options, func);
        });
        //如果没有动画在运行,运行动画
        //动画锁inprogress
        if(Queue[0]!=='inprogress'){
          dequeue()
        }

      }

      /*动画*/
      const animation = function(element,options) {

        const doAnimation = function(element, options, func) {
          const width = options.width

          /*===这里面定义了动画的算法,也就是Animation实现的地方===*/
          // 默认动画时长2s
          element.style.transitionDuration = '400ms';
          element.style.width =  width + 'px';

          /*监听单个动画完结*/
          //transitionend 事件在 CSS 完成过渡后触发
          element.addEventListener('transitionend', function() {
            func()
          });
        }
        //每调用一次animation,就入一次队
        return queue(element, options,doAnimation,);
      }


      //为chenQuery的fn和prototype原型属性 赋 animate属性
      chenQuery.fn = chenQuery.prototype = {
        //也可以直接把animation里的代码放这里来,但这样就太长了,降低了可读性
        animate: function(options) {
          animation(this.element, options);
          //注意返回的是this,也就是$("#A"),这样就能继续调用animate方法
          // 也就是链式调用
          return this;
        }
      }
      //为chenQuery的fn属性添加init方法
      const init = chenQuery.fn.init = function(selector) {
        // ["#A", "A",groups: undefined,index: 0,input: "#A"]
        const match = rquickExpr.exec(selector);
        //这边默认是只找id的元素
        const element = document.getElementById(match[1])
        //this指chenQuery.fn.init方法
        //为该方法添加element属性
        this.element = element;
        //返回chenQuery.fn.init
        return this;
      }
      //挺绕的,再将init的原型等于chenQuery.fn方法
      init.prototype = chenQuery.fn;

      //chenQuery本身是一个function(){}
      // chenQuery{
      //init能调用fn,fn能调用init
      //   fn:{
      //     animate:function(){},
      //     init:function(){},
      //     // init.prototype=fn
      //   },
      //   prototype:{
      //     animate:function(){},
      //   }
      // }

      return chenQuery;
    }());


  const A = document.querySelector('#A');
  //在异步调用中,进行同步调用
  //动画是异步的
  A.onclick = function() {
    //就是连续调用animation.add()
    $('#A').animate({
      'width': '500'
    }).animate({
      'width': '300'
    }).animate({
      'width': '1000'
    });
  };

</script>
</body>
</html>

jQuery之模拟实现$().animate()(上)

解析:

(1)匿名函数自调用的参数:

(function(a){
     console.log(a) //name
   })('name')
  
   (function (b) {
     console.log(b) //function(){console.log('name')}
   })(function () {
     console.log('name')
   })

(2)快速匹配id选择器

//匹配ID
      let rquickExpr = /^(?:#([\w-]*))$/;

(3)inprogress是动画锁

当第一个动画执行时,向 Queue 中添加锁 inprogress ,阻止异步调用动画,也就是要求同步执行动画,当动画结束时,移除锁,调用下一个动画。

(4)transitionend

transitionend 事件在 CSS 完成过渡后触发,这里当做单个动画完成的信号,触发后,会告知下个动画进行

下图的实现将在 下篇 文章贴出:

jQuery之模拟实现$().animate()(上)

jQuery之模拟实现$().animate()(上)

(完)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

关注码农网公众号

关注我们,获取更多IT资讯^_^


查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

An Introduction to Genetic Algorithms

An Introduction to Genetic Algorithms

Melanie Mitchell / MIT Press / 1998-2-6 / USD 45.00

Genetic algorithms have been used in science and engineering as adaptive algorithms for solving practical problems and as computational models of natural evolutionary systems. This brief, accessible i......一起来看看 《An Introduction to Genetic Algorithms》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

SHA 加密
SHA 加密

SHA 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具