内容简介:根据上图实现除
根据上图实现除 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游戏开发
[美] Vladimir Silva / 王恒、苏金国 等 / 人民邮电出版社 / 2011-2 / 45.00元
作为引领移动技术潮流的软件平台,Android发布了NDK以支持Java和C的混合开发,使PC游戏可以在Android平台上焕发更多魅力。 本书是为那些在Android游戏开发工作中寻求突破的人准备的。书中不仅通过Space Blaster和Asteroids这两个炫酷 的街机游戏深入介绍了如何从头构建纯Java游戏,更详细展示了如何将PC上的3D经典游戏Doom和Wolfenstein 3......一起来看看 《精通Android游戏开发》 这本书的介绍吧!