写在前面 自己的一点想法
"解决一个问题,最重要的收获并不是得到的答案。而是在寻找答案的过程中,学到的其它东西和见识的延伸。"
---《反正我从中学到不少东西》
”我敬你是条汉子!“
---《论如何回答女朋友问为什么对她那么好》
希望能够把文章大致扫一遍,里面有一些有趣的demo哦......哒
效果见页面顶部 或者如下:
显示border 隐藏border 显示切换栏 隐藏切换栏 等等api见下面描述
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
//---------------初始化轮显的方法-----------------------
$( "#modelSlider" ).slider({
imgs: [ //图片的地址
"http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_0f8738e9cfbb9485.png" ,
"http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_89e657a08f9f13f6.png" ,
"http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_884e69c2eb02316b.png" ,
"http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_462506e0ed7b0c25.png" ,
"http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_e5859ff3e6487575.png" ,
"http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_f07bd295f4cdbd7a.png"
],
urls: [ //点击图片跳转到的地址,也可以如下放一段js
‘javascript:makeDialog("轮显提示或者地址","第1个图",function(){},3)‘ ,
‘javascript:makeDialog("轮显提示或者地址","第2个图",function(){},3)‘ ,
‘javascript:makeDialog("轮显提示或者地址","第3个图",function(){},3)‘ ,
‘javascript:makeDialog("轮显提示或者地址","第4个图",function(){},3)‘ ,
‘javascript:makeDialog("轮显提示或者地址","第5个图",function(){},3)‘ ,
‘javascript:makeDialog("轮显提示或者地址","第6个图",function(){},3)‘
],
scale: 5 / 2, //图片宽高比
border: false , //是否显示分界线
showBar: true , //是否可以人工切换
x: 4, //横向格子数
y: 3 //纵向格子数
});
//---------------控制轮显的方法-----------------------
$( "#modelSlider" ).slider( "begin" ); //开始 执行某个方法
$( "#modelSlider" ).slider( "stop" ); //停止
$( "#modelSlider" ).slider( "choseImg" ,3); //切换到索引为3的项 执行某个方法,传参
$( "#modelSlider" ).slider( "resize" ,{border: true ,showBar: false }); //对初始化的属性进行修改
//-----------试试把上面这4行依次放到控制台执行一下?------
|
一、照着效果分析原理
最初是在一个叫《琉璃神社》的地方看到:http://hacg.club/。观察了很多次,觉得重点在这里:格子内的效果切换
。
于是就扒开看看喽...
观察了整个轮显很久之后,我初步得出以下几个想法。
总效果
=> 格子特效 + 效果产生顺序
格子
=> 2个div + 通过背景图切换
通过背景图切换 || 效果产生顺序
=> 可以用jQuery的队列处理Σ( ?д?))
具体的逻辑算法
=> 边写边想吧,写完重构
- ......
二、搭建jQuery插件结构
我觉得应该写成插件方式,毕竟要多处用。以下是我写插件一般的格式,欢迎拍砖:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// jQuery 插件的一般写法,自执行匿名方法
// 好处是这样的:1.避免其它插件也用了$做关键字;2.避免插件内部方法污染全局
// 实际工作中我一个js文件也许会写大几十个function,,,没办法,需求是一点一点加
( function ($) {
function Slider(option) {
//深拷贝,修改每个对象的属性只能通过对象实例,避免初始化时候外部引用对象的影响
this .opt = $.extend( true , {}, option);
}
$.fn.slider = function (option) {
var defaults = { //默认设置
// 独立写出来,也许将来就用得到呢,也说不定...
};
//最终配置
var opt = $.extend({}, defaults, option);
//jQuery对象是一个伪数组对象,可能有多个元素
return $.each( this , function (index, ele) {
// code...
var slider = new Slider(opt);
$(ele).data( "slider" , slider);
});
};
})(jQuery);
|
总结:
- 最基本的面向对象思想,写个类吧,在类中实现所有功能.
- 对jQuery.fn进行扩展,可以用 $.fn.method = function ,或者 $.fn.extend({}) .
- jQuery对象是一个伪数组对象,里面可能含有多个元素,需要针对每一个元素实例化一个对象进行缓存.
- 说到data方法,js对象的 $({}).data ,是把数据放到对象本身上,而元素的 data 方法,是把数据放到 $.cache 中 。所以如何跨框架使用easyui等报错的解决方式,是需要用所属iframe内的jQuery对象,否则取不到。
- 将所有代码放到匿名自执行方法中.
三、对将要用到的几个主要方法方法进行扩展
1.肯定要拼接html的,"<div id=‘"+theId+"‘ >....... 这种写法简直弱爆了,以前也经常这么写,但是某天就突然扩展了,,,果然多读读别人的文章对自己有好处.
?
1
2
3
4
5
6
7
8
9
10
11
|
//扩展 string.format
String.prototype.format = function () {
var args = arguments;
var reg = /\{(\d+)\}/g;
return this .replace(reg, function (g0, g1) {
return args[+g1];
});
};
//用法:
"hello {0},your age is {1},so {0}‘s age is {1}" .format( "tom" ,12);
//"hello tom,your age is 12,so tom‘s age is 12"
|
说明:
- 对String原型进行扩展: String.prototype.methodName=function...
- 正则表达式: /\{(\d+)\}/g ;取"{0}"这种格式的占位符,并对里面的数字放入子组
- js 的 replace 方法有一种重载, string.format(regex , function(group0【匹配项】,group1【子组第一个】...){ //code... }) ;对于每次匹配到的一个占位符,都从参数相应的位置取得替换项。
2.图片预加载
?
1
2
3
4
5
6
7
8
9
10
11
|
( function ($) { // 图片预加载
$.preLoad = function (urlArr) {
$.each(urlArr, function (index, url) {
var img = document.createElement( "img" );
img.src = url;
});
}
})(jQuery);
//上来就加载大量图片会占用大量带宽,影响用户体验
//但是如果轮显这里不提前加载,只在显示当前图片的时候去下载当前图片,对于一般网速的用户来说,可能不太好看
//根据实际情况使用吧...哒?
|
3.jQuery队列封装
关于jQuery队列的一点认识:
众所周知,使用jQuery给元素添加一连串的动画效果,元素并不会将动画同时执行,而是按照添加的顺序,依次在上一个动画结束之后才开始下一个动画。
我了解的情况就是,jQuery使用了一种叫做“队列”(queue)的方式将动画效果依次加进去,在上一个队列中的动画执行完毕,通过deferred通知下一个动画执行。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var ele = $( "#id" ); //某个jQuery对象
//为jQuery对象的叫“queueName”的队列上面添加处理事件
ele.queue( "queueName" , function (next) {
//your code... do something
next(); //next() 是执行下一个队列中要处理的事件,如果没有next队列就无法依次处理
});
//延时
ele.delay(1000, "queueName" );
//执行队列
ele.dequeue( "queueName" );
|
这里要说一下的是,jQuery的动画默认是把处理事件放在了叫“fx”的队列中。因此,我进行了以下简单的封装:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
$.fn.will = function (callback, type) {
//这里的this,表示jQuery对象
this .queue(type || "fx" , function (next) { // fx 表示默认的队列
//这里的this,是原生的对象
callback && typeof callback == "function" && callback.call($( this )); //使用call,方便回调函数使用this
next();
});
return this ; //返回this,方便进行链式调用
}
//试试在控制台这么用
var ele = $({});
for ( var i = 0; i < 10; i++) {
ele.will( function () {
console.log(+ new Date);
}).delay(1000);
}
|
使用队列,可以直观清晰,方便地将异步操作表示出来。就像 Thread.Sleep(1000)
那样明了。
关于Deferred我就不赘述了,本文没有直接使用到,自己也只是知其然而不知其所以然,仅仅会用。
队列的作用,就是将轮显中的格子,一个一个进行处理,避免了大量的setTimeout,使用callback的形式进行替换。
四、缓动
先看例子,没有效果图吸引不了人
点击发射
更详细的缓动介绍请参见:http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html
这里我介绍一下jQuery.animate的一种重载
jQuery的animate动画,我以前不知道在哪里看到的:只能实现可以用数字表示的动画。也就是说css3的transform是不行的。但是animate有一种重载!
常用的方式
:
?
1
|
$( "html,body" ).animate({ scrollTop: "0px" }, 1000);
|
另一种重载
:
?
1
2
3
4
5
6
7
8
9
|
$({ num: 32 }).animate({ num: 64 }, {
duration:1000,
step: function () {
console.log( "当前的num是:" + this .num);
},
complete: function () {
console.log( "结束了,num是:" + this .num);
}
});
|
看到上面的写法,就应该大致了解了demo中动画的原理:
【根据要改变的样式定义一个对象,利用animate改变这个对象,监听step和complete事件来拼接新的样式赋值给你要执行动画的元素!】
以下是【发射愤怒的小鸟】
的具体实现
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
jQuery.extend(jQuery.easing, {
easeOutBounce: function (x, t, b, c, d) {
if ((t /= d) < (1 / 2.75)) {
return c * (7.5625 * t * t) + b;
} else if (t < (2 / 2.75)) {
return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
} else if (t < (2.5 / 2.75)) {
return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
} else {
return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
}
},easeOutCubic: function (x, t, b, c, d) {
return c * ((t = t / d - 1) * t * t + 1) + b;
}
})
function sendBirld() {
var ele = $( "#birld" ).stop( true , false );
ele.css({ "left" : "0" , "top" : "0" , "transform" : "rotateZ(0deg)" });
$({ left: 0, top: 0, tran: 0 }).animate({
left: 800, top: 180, tran: 360
}, {
duration: 2500,
specialEasing: {
left: ‘easeOutCubic‘ ,
top: ‘easeOutBounce‘
},
step: function () {
ele.css({ "left" : this .left + "px" , "top" : this .top + "px" , "transform" : "rotateZ(" + this .tran + "deg)" });
},
complete: function () {
ele.css({ "left" : "800px" , "top" : "180px" , "transform" : "rotateZ(360deg)" });
}
});
}
|
五、对js异步编程的思考学习
我目前了解到3种js异步的方式:setTimeout,setInterval
,回调函数
,事件触发
setTimeout和setInterval太丑陋了...虽然大部分误差可以接受,但是总归并不是赏心悦目。而且有些东西并不清楚会执行多久,所以舍弃。
事件触发,让我想到了 C# 中的事件与委托,确实不错,但是一长串任务要定义多少事件?感觉沉重。 这一块了解的不深,可能说的不正确。
我偏向于第二种回调。
?
1
2
3
4
|
function work(callback) {
//do something...
typeof callback == "function" && callback();
}
|
但是天啊,如果一长串方法需要依次执行,这回调要有多难看?
我们看看jQuery是怎么做的(只说用法,实现过程没研究):
jQuery.Deferred()的一点了解
$.Deferred()是jQuery1.5开始加进去的,并重写了 ajax和animate(基于queue,queue基于Deferred)
使用示例:
?
1
2
3
4
5
6
7
8
9
10
11
12
|
function work() {
var dfd = $.Deferred();
setTimeout( function () {
//do something...
dfd.resolve();
},1000);
return dfd;
}
work().done( function () {
window.console && console.log( "结束了" );
});
|
使用方式:1.创建deferred对象;2.为该对象暴漏的事件绑定方法;3.对象执行动作,触发绑定的方法
对应的动作和事件(我目前常用的):
- deferred.resolve() => deferred.done(callback) //完成
- deferred.reject() => deferred.fail(callback) //失败
- deferred.then(cb1,cb2) //cb1完成,cb2失败,当然有cb3,这个没做具体了解
- deferred.always(callback) //无论完成或者失败
- jQuery.when(dfd1,dfd2...)的用法:
?
1
2
3
4
5
6
7
8
|
//参数是若干个deferred或者promise对象
$.when(dfd1, dfd2, dfd3...).done( function () {
//全都完成时候触发
}).fail( function () {
//有一个失败则判定全部失败
}).always( function () {
//全都是完成或者失败状态时候触发
});
|
- //注:动作中的参数,会自动带入到事件回调的参数位置,如:
?
1
2
3
4
5
|
var dfd = $.Deferred();
dfd.done( function (str) {
console.log(str);
});
dfd.resolve( "lalala" ); //会打印出 "lalala"
|
- ......
类似于C#中的委托与事件:委托的发布者不应该将委托的操控权暴漏给订阅者,最好用事件对委托进行安全的封装。 直接返回deferred似乎也不太好,对deferred仍然可以操作,所以封装一下:返回deferred.promise(),该对象只暴漏了事件的订阅方法,而不能操作。
看看 jQuery.ajax
传统的jQuery.ajax
?
1
2
3
4
5
6
7
8
9
10
11
12
|
$.ajax({
//...
success: function () {
//...
},
error: function () {
//...
},
complete: function () {
//...
}
});
|
ajax方法返回的仍然是一个promise对象,提供事件订阅的方法:done,fail,then...为了与原方法名对应,看下图,也额外提供了原来的名称:
另一种用法
?
1
2
3
4
5
6
7
8
9
|
$.ajax({
//...
}).success( function (data) {
//原success 或使用 done
}).error( function () {
//原error 或使用 fail
}).complete( function () {
//原complete 或类似用使用 always
});
|
这时候我想了想,我要在函数里面返回deferred对象么?有点麻烦...
突然想到jQuery的动画添加进去就会依次执行。于是了解到动画是基于队列的:
六、总结,下载
总结:
本文很多地方介绍的可能都不是很详细,毕竟我以一个“过来人”的思考方式,对于初次接触人的想法不匹配,相信那些已经掌握的人来说就是:“对啊,就这样子啊。”,初接触:“啥?你到底想说啥?”
似乎有点仓促,但是我觉得了解以上内容就已经够了。且不行,就当做目录看,对于各个知识点再去找专门的文章进行深入学习。
按照最开始的分析,已经解决了:按顺序依次延时处理(queue队列,js异步),jQuery插件的写法,格子切换时的缓动处理,其中间杂着一些在学习过程中的思考和扩展(我觉得在寻求答案中的扩展很重要)。 剩下的大概就是具体实现了...无非就是用绝对定位,在切换的时候使用缓动做特效,用queue来进行异步处理,需要一些想法,简单的算法,html和css基础。
下面附上下载地址:slider1.2.js ,slider.min.css
我在制作这个插件的过程中,巩固和学习了不少知识,实现一个功能,重要的不仅仅是实现,更多的是在实现过程中的自我扩展和见识的延伸。
突然想到了一个广告词:人生就是一部旅行,重要的不是目的地,而是沿途的风景,以及看风景的心情。
http://www.cnblogs.com/lianmin/p/4625835.html
时间: 2024-10-05 20:37:03