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

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

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

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()(上)

(完)


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

查看所有标签

猜你喜欢:

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

禅与摩托车维修艺术

禅与摩托车维修艺术

(美)罗伯特·M.波西格 / 张国辰 / 重庆出版社 / 2011-9 / 36.00元

在一个炎热的夏天,父子两人和约翰夫妇骑摩托车从明尼苏达到加州,跨越美国大陆,旅行的过程与一个青年斐德洛研修科学技术与西方经典,寻求自我的解脱,以及探寻生命的意义的过程相互穿插。一路上父亲以一场哲学肖陶扩的形式,将见到的自然景色,野外露营的经历,夜晚旅店的谈话,机车修护技术等等日常生活与西方从苏格拉底以来的理性哲学的深入浅出的阐述与评论相结合,进行了对形而上学传统的主客体二元论的反思,以及对科学与艺......一起来看看 《禅与摩托车维修艺术》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

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

HSV CMYK互换工具