分享一款基于jqery的带3D切换效果的图片展示

  先看效果:在线演示

  这个效果并不是我想出来的,我只是对某个开源的flash图片展示(请原谅我并不知道原作的链接……)使用js重写罢了。

  起因是,我所在学校的网站(相思湖网站)要进行改版,其中各专题首页需要一个图片展示。某成员找到了一个带3D切换效果的图片展示,可惜是flash做的,并且在使用的过程中有一个问题,如果图片的宽高与原始定义的不同,就会出现一个固定的白框。

  当时我的第一反应就是为什么要flash?难道js做不到么?话虽如此,但如果可以改改代码就能解决的话,倒也省事。终归我过于乐观了,尽管as和js是近亲,我却总抓不住问题的关键所在,一部分是因为对flash的不熟悉,令一部分也因为那as代码写得也够凌乱的。总之我决定了要用js重写。

  仔细想想这个效果并不很难实现,借助jquery的animation可以轻松实现节点元素的各种动画,唯一的难点是确定图片的位置而已了。

  我是利用等比对折来确定图片的位置:  

  

  假设整个框架的长度是W,高度是H,图片的长为w,高为h。那么居中的图片的top为(H - h) / 2,left为(W - w) / 2,旁边图片的计算方法类同。

  源代码:

js
  1 /*
  2  * xsh slider for jquery
  3  * By: QiuXiang, qiuxiang55aa@gmail.com
  4  * Used In: http://xsh.gxun.edu.cn
  5  *
  6  * Copyright 2012, XSH
  7  * Free to use and abuse under the MIT license.
  8  * http://www.opensource.org/licenses/mit-license.php
  9  */
 10 (function($){
 11     $.fn.xsh_slider = function(options){
 12         var opts = $.extend({}, $.fn.xsh_slider.defawrapts, options);
 13         var $this = $(this);
 14         var wrap = $('ul', $this);
 15         var imgs = [];
 16         var current = 1;
 17         var pre_img;
 18         var cur_img;
 19         var next_img;
 20         var timeout;
 21 
 22         init();
 23 
 24         function pre()
 25         {
 26             unbind_click();
 27 
 28             next_img.li.removeClass('next_img');
 29             cur_img.li.removeClass('cur_img');
 30             pre_img.li.removeClass('pre_img');
 31 
 32             current = (current == 0 ? imgs.length - 1 : current - 1);
 33             var pre_i = (current == 0 ? imgs.length - 1 : current - 1);
 34             var _next_img = next_img;
 35             next_img = cur_img;
 36             cur_img = pre_img;
 37             pre_img = imgs[pre_i];
 38 
 39             next_img.li.addClass('next_img');
 40             cur_img.li.addClass('cur_img');
 41             pre_img.li.addClass('pre_img');
 42 
 43             // 动画切换
 44             next_hide(_next_img);
 45             goto_next(next_img);
 46             goto_cur(cur_img);
 47             pre_init(pre_img);
 48             goto_pre(pre_img);
 49 
 50             alt_hide(next_img);
 51             alt_show(cur_img);
 52 
 53             bind_click();
 54             timeout_reset();
 55         }
 56 
 57         // 切换下一张图片
 58         function next()
 59         {
 60             unbind_click();
 61 
 62             pre_img.li.removeClass('pre_img');
 63             cur_img.li.removeClass('cur_img');
 64             next_img.li.removeClass('next_img');
 65 
 66             current = ((current == imgs.length - 1) ? 0 : current + 1);
 67             var next_i = (current == imgs.length - 1) ? 0 : current + 1;
 68             var _pre_img = pre_img;
 69             pre_img = cur_img;
 70             cur_img = next_img;
 71             next_img = imgs[next_i];
 72 
 73             pre_img.li.addClass('pre_img');
 74             cur_img.li.addClass('cur_img');
 75             next_img.li.addClass('next_img');
 76 
 77             // 动画切换
 78             pre_hide(_pre_img);
 79             goto_pre(pre_img);
 80             goto_cur(cur_img);
 81             next_init(next_img);
 82             goto_next(next_img);
 83 
 84             alt_hide(pre_img);
 85             alt_show(cur_img);
 86 
 87             bind_click();
 88             timeout_reset();
 89         }
 90 
 91         // pre_img 的消逝
 92         function pre_hide(img)
 93         {
 94             img.li.animate({
 95                 width: 0,
 96                 height: 0,
 97                 left: 0,
 98                 top: opts.height / 2,
 99                 opacity: 0
100             }, {
101                 duration: opts.speed,
102                 easing: 'easeOutExpo',
103                 queue: false
104             });
105         }
106 
107         // next_img 的消逝
108         function next_hide(img)
109         {
110             img.li.animate({
111                 width: 0,
112                 height: 0,
113                 left: opts.width,
114                 top: opts.height / 2,
115                 opacity: 0
116             }, {
117                 duration: opts.speed,
118                 easing: 'easeOutExpo',
119                 queue: false
120             });
121         }
122 
123         // 切换到 pre_img
124         function goto_pre(img)
125         {
126             img.li.animate({
127                 width: img.pre.width,
128                 height: img.pre.height,
129                 left: img.pre.left,
130                 top: img.pre.top,
131                 opacity: 1
132             }, {
133                 duration: opts.speed,
134                 easing: 'easeOutExpo',
135                 queue: false
136             });
137         }
138 
139         // 切换到 cur_img
140         function goto_cur(img)
141         {
142             img.li.animate({
143                 width: img.center.width,
144                 height: img.center.height,
145                 left: img.center.left,
146                 top: img.center.top,
147                 opacity: 1
148             }, {
149                 duration: opts.speed,
150                 easing: 'easeOutExpo',
151                 queue: false
152             });
153         }
154 
155         // 切换到 next_img
156         function goto_next(img)
157         {
158             img.li.animate({
159                 width: img.next.width,
160                 height: img.next.height,
161                 left: img.next.left,
162                 top: img.next.top,
163                 opacity: 1
164             }, {
165                 duration: opts.speed,
166                 easing: 'easeOutExpo',
167                 queue: false
168             });
169         }
170 
171         // 绑定图片的点击切换事件
172         function bind_click()
173         {
174             $('.pre_img', $this).click(function(){
175                 pre();
176                 return false;
177             });
178             $('.next_img', $this).click(function(){
179                 next();
180                 return false;
181             });
182         }
183         
184         // 取消绑定图片的点击切换事件
185         function unbind_click()
186         {
187             $('.pre_img').unbind();
188             $('.next_img').unbind();
189         }
190 
191         // 重置自动播放
192         function timeout_reset()
193         {
194             clearInterval(timeout);
195             auto_play();
196         }
197 
198         // 显示图片说明
199         function alt_show(img)
200         {
201             if (img.div.text() != '')
202                 img.div.css({'display': 'block'});
203         }
204 
205         // 隐藏图片说明
206         function alt_hide(img)
207         {
208             img.div.css({'display': 'none'});
209         }
210 
211         // 创建图片切换按钮
212         function btn_create()
213         {
214             wrap.append('<div class="btn_pre"><a>' + opts.pre_text + '</a></div>');
215             wrap.append('<div class="btn_next"><a>' + opts.next_text + '</a></div>');
216 
217             var btn_pre = $('.btn_pre', $this);
218             var btn_next = $('.btn_next', $this);
219 
220             btn_pre.css({'top': (opts.height - btn_pre.height()) / 2});
221             btn_next.css({'top': (opts.height - btn_next.height()) / 2});
222 
223             btn_pre.click(function(){
224                 pre();
225             });
226             btn_next.click(function(){
227                 next();
228             });
229         }
230 
231 
232         // 作为上一个图片
233         function as_pre(img)
234         {
235             img.li.css({
236                 'width': img.pre.width,
237                 'height': img.pre.height,
238                 'left': img.pre.left,
239                 'top': img.pre.top,
240                 'opacity': 1
241             });
242         }
243 
244         // 作为当前图片
245         function as_cur(img)
246         {
247             img.li.css({
248                 'width': img.center.width,
249                 'height': img.center.height,
250                 'left': img.center.left,
251                 'top': img.center.top,
252                 'opacity': 1
253             });
254         }
255 
256         // 作为下一个图片
257         function as_next(img)
258         {
259             img.li.css({
260                 'width': img.next.width,
261                 'height': img.next.height,
262                 'left': img.next.left,
263                 'top': img.next.top,
264                 'opacity': 1
265             });
266         }
267 
268         // 下一个图片出现的初始化
269         function next_init(img)
270         {
271             img.li.css({
272                 'width': 0,
273                 'height': 0,
274                 'left': opts.width,
275                 'top': opts.height / 2,
276                 'opacity': 0
277             });
278         }
279 
280         // 上一个图片出现的初始化
281         function pre_init(img)
282         {
283             img.li.css({
284                 'width': 0,
285                 'height': 0,
286                 'left': 0,
287                 'top': opts.height / 2,
288                 'opacity': 0
289             });
290         }
291 
292         // 图片初始化
293         function img_init()
294         {
295             // 遍历图片,创建图片状态缓存
296             $('li', $this).each(function(){
297                 var _this = $(this);
298                 var img = $('img', _this);
299                 var alt = img.attr('alt') || '';
300                 var width = img.width();
301                 var height = img.height();
302 
303                 _this.append('<div class="alt"><p>' + alt + '</p></div>');
304                 imgs.push({
305                     img: img,
306                     li: _this,
307                     div: $('div', _this),
308                     center: {
309                         width: width,
310                         height: height,
311                         left: (opts.width - width) / 2,
312                         top: (opts.height - height) / 2
313                     },
314                     pre: {
315                         width: width / 2,
316                         height: height / 2,
317                         left: (opts.width - width) / 4,
318                         top: opts.height / 2 - height / 4
319                     },
320                     next: {
321                         width: width / 2,
322                         height: height / 2,
323                         left: opts.width * 3 / 4- width / 4,
324                         top: opts.height / 2 - height / 4
325                     }
326                 });
327                 img.width('100%').height('100%');
328             });
329 
330             pre_img = imgs[0];
331             cur_img = imgs[1];
332             next_img = imgs[2];
333             current = 1;
334 
335             pre_img.li.addClass('pre_img');
336             cur_img.li.addClass('cur_img');
337             next_img.li.addClass('next_img');
338 
339             as_pre(pre_img);
340             as_cur(cur_img);
341             as_next(next_img);
342 
343             pre_img.li.show();
344             cur_img.li.show();
345             next_img.li.show();
346             alt_show(cur_img);
347         }
348 
349         function wrap_init()
350         {
351             wrap.addClass('xsh_slider');
352             wrap.css({
353                 'width': opts.width,
354                 'height': opts.height
355             });
356         }
357 
358         // 自动播放
359         function auto_play()
360         {
361             if (opts.auto)
362             {
363                 timeout = setInterval(function(){
364                     next();
365                 }, opts.delay);
366             }
367         }
368 
369         // 初始化
370         function init()
371         {
372             wrap_init();
373             btn_create();
374             img_init();
375             bind_click();
376             auto_play();
377             mousewheel();
378         }
379 
380         // 鼠标滚轮事件
381         function mousewheel()
382         {
383             wrap.mousewheel(function(event, delta, deltaX, deltaY){
384                 if (delta > 0)
385                     next();
386                 else
387                     pre();
388 
389                 return false;
390             });
391         }
392     };
393 
394     // 默认参数
395     $.fn.xsh_slider.defawrapts = {
396         pre_text: '<',
397         next_text: '>',
398         width: 960,
399         height: 400,
400         speed: 500,
401         delay: 5000,
402         auto: true
403     };
404 
405     // 阻尼动画切换效果
406     $.extend(
407         $.easing, {
408             easeOutExpo: function (x, t, b, c, d) {
409                 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
410             }
411         }
412     );
413 })(jQuery);
414 
415 // 引用的鼠标滚轮 jquery 插件
416 /*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
417  * Licensed under the MIT License (LICENSE.txt).
418  *
419  * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
420  * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
421  * Thanks to: Seamus Leahy for adding deltaX and deltaY
422  *
423  * Version: 3.0.6
424  *
425  * Requires: 1.2.2+
426  */
427 (function($){
428     var types = ['DOMMouseScroll', 'mousewheel'];
429 
430     if ($.event.fixHooks) {
431         for ( var i=types.length; i; ) {
432             $.event.fixHooks[ types[--i] ] = $.event.mouseHooks;
433         }
434     }
435 
436     $.event.special.mousewheel = {
437         setup: function() {
438             if ( this.addEventListener ) {
439                 for ( var i=types.length; i; ) {
440                     this.addEventListener( types[--i], handler, false );
441                 }
442             } else {
443                 this.onmousewheel = handler;
444             }
445         },
446 
447         teardown: function() {
448             if ( this.removeEventListener ) {
449                 for ( var i=types.length; i; ) {
450                     this.removeEventListener( types[--i], handler, false );
451                 }
452             } else {
453                 this.onmousewheel = null;
454             }
455         }
456     };
457 
458     $.fn.extend({
459         mousewheel: function(fn) {
460             return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
461         },
462 
463         unmousewheel: function(fn) {
464             return this.unbind("mousewheel", fn);
465         }
466     });
467 
468     function handler(event) {
469         var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
470         event = $.event.fix(orgEvent);
471         event.type = "mousewheel";
472 
473         // Old school scrollwheel delta
474         if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta/120; }
475         if ( orgEvent.detail ) { delta = -orgEvent.detail/3; }
476 
477         // New school multidimensional scroll (touchpads) deltas
478         deltaY = delta;
479 
480         // Gecko
481         if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
482             deltaY = 0;
483             deltaX = -1*delta;
484         }
485 
486         // Webkit
487         if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; }
488         if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; }
489 
490         // Add event and delta to the front of the arguments
491         args.unshift(event, delta, deltaX, deltaY);
492 
493         return ($.event.dispatch || $.event.handle).apply(this, args);
494     }
495 
496 })(jQuery);
css
 1 .xsh_slider {
 2     padding: 0;
 3     list-style: none;
 4     overflow: hidden;
 5     position: relative;
 6 }
 7 .xsh_slider li {
 8     position: absolute;
 9     overflow: hidden;
10     opacity: 0;
11     filter: alpha(opacity = 0);
12 }
13 .xsh_slider .alt {
14     position: absolute;
15     bottom: 0;
16     display: none;
17 }
18 .xsh_slider img {
19     border: none;
20 }
21 .xsh_slider .pre_img, .xsh_slider .next_img {
22     z-index: 1;
23     cursor: pointer;
24 }
25 .xsh_slider .cur_img {
26     z-index: 2;
27 }
28 .xsh_slider .btn_pre, .xsh_slider .btn_next {
29     position: absolute;
30     cursor: pointer;
31 }
32 .xsh_slider .btn_pre {
33     left: 0;
34 }
35 .xsh_slider .btn_next {
36     right: 0;
37 }

  惭愧的说,代码写得不怎么样,纯粹面向过程写法。

  最后附上下载:xsh_slide.7z

posted @ 2012-08-23 14:54  7c00  阅读(821)  评论(5编辑  收藏  举报