内容简介:根据上图实现除
根据上图实现除 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>
解析:
(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 完成过渡后触发,这里当做单个动画完成的信号,触发后,会告知下个动画进行
下图的实现将在 下篇 文章贴出:
(完)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- php如何实现session,自己实现session,laravel如何实现session
- AOP如何实现及实现原理
- webpack 实现 HMR 及其实现原理
- Docker实现原理之 - OverlayFS实现原理
- 为什么实现 .NET 的 ICollection 集合时需要实现 SyncRoot 属性?如何正确实现这个属性?
- 自己实现集合框架(十):顺序栈的实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
第一行代码:Android(第2版)
郭霖 / 人民邮电出版社 / 2016-12-1 / CNY 79.00
本书被广大Android 开发者誉为“Android 学习第一书”。全书系统全面、循序渐进地介绍了Android软件开发的必备知识、经验和技巧。 第2版基于Android 7.0 对第1 版进行了全面更新,将所有知识点都在最新的Android 系统上进行重新适配,使用 全新的Android Studio 开发工具代替之前的Eclipse,并添加了对Material Design、运行时权限、......一起来看看 《第一行代码:Android(第2版)》 这本书的介绍吧!