jQuery幻灯片插件开发

憋了N天,终于整出来个jQuery的幻灯片插件。jQuery的插件资源非常丰富(25个必须学会的jQuery幻灯片插件教程),没有必要重复发明轮子,任务需要或技能训练,必要的时候还是要动手去做一下,有利于提高JS能力。

先来看一下如何使用该插件,知道如何使用jQuery访问DOM,就可以轻松使用该插件。当然要先从HTML结构开始出发。

HTML代码

<div id="ad_gallery">
    <div class="ad_sheet_wrap">
        <ul class="ad_sheet_con">
            <li><a href="#"><img src="image/image_1.jpg"></a></li>
            <li><a href="#"><img src="image/image_2.jpg"></a></li>
            <li><a href="#"><img src="image/image_3.jpg"></a></li>
            <li><a href="#"><img src="image/image_4.jpg"></a></li>        
            <li><a href="#"><img src="image/image_5.jpg"></a></li>                    
        </ul>
    </div>
</div>

这是幻灯片所必须的HTML结构,默认自动切换,如果感觉不简洁,那也没办法了。.ad_sheet_wrap和.ad_sheet_con是默认的类名,如果想要改变它的名字,可以在调用插件的时候以参数的形式传递过去。

CSS代码

* {margin:0; padding: 0;}
ul {list-style-type: none;font-size: 0;}
img {border: 0;}
.ad_sheet_wrap {width:514px; height:191px; overflow:hidden; position:relative;}
.ad_sheet_con {position: absolute;}

样式代码一样如此简洁,主要涉及基础的定位知识。需要注意的是,在IE6、7中,上下滚动是,li标签会出现几个像素的空白。详情请参考无序列表ul在IE6,IE7出现的下边距BUG

JavaScript代码

jQuery('#ad_gallery').adGallery();

如何导入jQuery库和插件库就不说了,估计应该都知道,以上是最简洁的幻灯片模式,可以查看效果图

如果要获得其它的附加效果,可以提供相对应的参数。详细参数如下。

options = {
    startIndex: 0,               // 默认从第一张图片开始
    autoPlay: true,              // 自动播放
    duration: 5000,              // 5秒切换一次
    direction: "top",            // 默认垂直,可用left
    event: "mouseover",          // 切换触发事件 
    sheet: 'img',                // 幻灯片外层元素
    thumb: 'span',               // 触发器外层元素
    thumbNav: false,             // 是否显示数字切换按钮
    adNav: false,                // 是否显示前一张、后一张按钮
    sheetWrap: '.ad_sheet_wrap', // 幻灯片容器 
    thumbWrap: '.ad_thumb_wrap', // 触发器容器
    sheetCon: '.ad_sheet_con',   // 幻灯片包裹层
}

以上是基本的使用方式。感觉没有什么难理解的地方。如果遇到问题或有疑问,请给我留言。

访问插件首页或者下载最新版本

下面讲解一下开发该插件的思路。

jQuery一般获取页面DOM对象,将其转换成jQuery对象,该对象就能访问jQuery提供的所有方法。可以扩展jQuery对象本身,将开发的插件绑定到jQuery对象上,但这样就无法使用 jQuery里最强大的链式调用了。jQuery提供了一个插件扩展接口(jQuery.fn),可以在该接口上扩展jQuery类。

// 扩展jQuery对象本身
$.adGallery = function(adGalleryCon, options) { } 

// 扩展jQuery提供的插件接口
$.fn.adGallery = function(options) {
    return this.each(function() {
        $(this).data('adGallery', new $.adGallery(this, options));
    });
}

基本的jQuery扩展方式一般就这两种,而且最常用的是两者混用,提供多种选择。

幻灯片一般通过控制HTML元素的left或者top属性来移动、切换幻灯片容器。下面的图片是Chrome浏览器运行时的HTML结构的截图。

从最简单的开始出发,幻灯片需要什么,也就是在规律的时间内切换幻灯展示。这是我认为的最基本的功能,其它的都是在此基础上进行扩展。数字触发器,上一张、下一张导航,都属于可选的功能之列。

从HTML结构上来说,要求并不是太多,必须按照插件提供的类名或者自定义变量来创建HTML结构。下面是基本的HTML结构。

<div class="ad_gallery">
    <div class="ad_sheet_wrap">
        <div class="ad_sheet_con">
            ......
        </div>
    </div>
    <div class="ad_thumb_wrap">
        ....
    </div>
</div

如何自定义自己的类名和标签,上面的默认属性里面已经提到了。需要一提的是,我认为数字触发器是可选的,并且是根据幻灯片的数量来动态添加到HTML结构中的,如果调用者自己提供了触发器,那么插件会认为调用者知道自己在做什么,会提供正确的触发器。

下面是插件的构造器

$.adGallery = function(adGalleryCon, options) {   
    var that = this, settings = $.extend({}, defaults, options || {}),
        adCon = $(adGalleryCon), 
        sheetWrap = $(settings.sheetWrap, adCon), 
        thumbWrap = $(settings.thumbWrap, adCon);
    
    this.adCon = adCon;        
    this.sheetWrap = sheetWrap;
    this.thumbWrap = thumbWrap;
    this.sheetCon = $(settings.sheetCon, sheetWrap);    
    this.sheetData = $(settings.sheet, this.sheetCon);
    this.sheetWidth = 0;
    this.sheetHeight = 0;
    this.thumbData = [];
        
    this.settings = settings; 
           
    this.initialize();    
           
    return this;        
};

初始化取得幻灯片容器和触发器容器,获取幻灯片的数量,存放到this.sheetData数组中,初始化触发器的容器为空数组,将在程序后面进行填充,主要的初始化部分在initialize()方法中。

initialize: function() {
    var settings = this.settings;
    
    this.dir = settings.direction;        
    this.curIndex = settings.startIndex > this.sheetData.length ? this.sheetData.length - 1 : settings.startIndex;
    this.oldIndex = 0;
    this.timer = null;
    
    this.initSheet();            
    
    this.bindHover(this.sheetWrap);
    
    if (settings['thumbNav'] || this.thumbWrap.length) this.initThumb();
    
    if (settings['adNav']) this.createAdNav();        
            
    if (settings['autoPlay']) this.autoPlay();                    
},

this.curIndex进行拦截处理,防止调用者提供超出幻灯片总数的起始数值。this.oldIndex属性存放上一次的幻灯片索引,主要为了避免触发器切换时执行for循环。

this.initSheet()用来初始化幻灯片容器。this.initThumb()用来初始化触发器。这两个部分比较重要,当然,不用触发器时后者就不重要了。

initSheet: function() {
    var sheet = $(this.sheetData[0]),
        sheetWidth = sheet.width() || this.sheetWrap.width(),
        sheetHeight = sheet.height() || this.sheetWrap.height();  

    this.sheetWrap.css({"position": "relative", "overflow": "hidden", "width": sheetWidth + "px", "height": sheetHeight + "px"});
    this.sheetCon.css({"position": "absolute"}); 
    
    $(this.settings.sheet, this.sheetCon).css({"width": sheetWidth + "px", "height": sheetHeight + "px", "overflow": "hidden"});
    
    if ('left' === this.dir) {
        this.sheetCon.css({"width": sheetWidth * this.sheetData.length + 'px', "left": (- this.curIndex * sheetWidth) + 'px'});
        $(this.settings.sheet, this.sheetCon).css({"float": "left"});
    } else {
        this.sheetCon.css('top', (- this.curIndex * sheetHeight) + 'px');
    }
    
    this.sheetWidth = sheetWidth;
    this.sheetHeight = sheetHeight;
},

这一段程序主要对幻灯片容器进行样式修改。幻灯片的宽度和高度通过jQuery动态获取,需要注意的是,如果提供的幻灯片标签是img,图片无法及时载入,只能从父容器上获取宽和高属性。再者,如果向水平滚动,需要设置幻灯片容器的宽度以及幻灯片的float属性。

initThumb: function() {
    var thumbWrap = this.thumbWrap;
    if (1 === thumbWrap.length) {
        this.bindThumbEvent($(this.settings.thumb, thumbWrap));          
    } else if (!!this.settings['thumbNav']) {
        this.createThumbNav();
    }    
    
    this.thumbData[this.curIndex].addClass('selected');
},

这部分程序用来初始化触发器,并且在this.bindThumbEvent()方法中将触发器压入到this.thumbData数组中,这在图片切换的时候要用到。

select: function(index) {
    if (this.thumbData.length) this.selectedThumb(index);
    
    if ('top' === this.dir) {
        this.sheetCon.stop().animate({top: -index * this.sheetHeight}, 300);              
    } else {
        this.sheetCon.stop().animate({left: -index * this.sheetWidth}, 300);              
    }
    this.curIndex = index; 
},    
selectedThumb: function(index) {
    var thumbData = this.thumbData;
                
    this.oldIndex = this.curIndex;
               
    thumbData[this.oldIndex].removeClass('selected');
    thumbData[index].addClass('selected');
},

主要的部分基本上就是这些。在select方法调用的时候,对触发器进行处理。上一个触发器移除selected类,下一个添加selected类,这就是上面说过的避免for循环,这样就必须在程序中处理好索引。实现幻灯片切换的部分在select方法中,其实,不用插件感觉实现代码量更少,但是弊端就是每次都要从头开始。

现在还没有评论

留下您的大名