图片轮播插件有很多,今天发现自己网站的幻灯片鼠标经过不能停止播放,还没有看清楚banner上的内容呢,就播放下一张图片了,很是郁闷。
就想着能不能找一个鼠标经过停止播放的轮播插件呢,无意间发现站酷的轮播banner图就是可以停止的,然后翻了一下它的源码,发现了一个名字叫Unslider的js文件,百度一下,在bootstrap官网看到了这个插件的推荐,真心好用啊。
具体效果如图:
下载地址↓
链接: https://pan.baidu.com/s/1dFNCozZ 密码: tvwn
可以看看bootstrap的推荐:超小的jquery轮滑插件unslider
结果bootstrap上面的文件不能下载,只能百度到一个压缩包,下载下来,不过是版本V1.0,站酷的是V2.0,我把站酷的下载下来,因为被站酷的工程师改变了源文件,结果我死活用不起,吐血。
GitHub上面的源文件我也死活下载不下来,看来翻墙软件势在必行。
那就用V1.0版本的,毕竟这个插件有两个特性我非常看重。就是支持鼠标经过停止播放和响应式布局。
一、Unslider插件特点
体积超小,3KB不到。
效果很简单,很纯粹的轮播。
CSS样式完全自定义,宽高在样式中定义,很灵活。
可以选择是否出现上一张下一张和下面的圆点翻页。
可以定义速度。
支持鼠标经过停止播放。
响应式布局,各种设备自适应。
支持移动端屏幕手势滑动,不过需要额外的插件。
二、使用方法
第1步:导入jquery库和unslider的js文件
<script type="text/javascript" src="js/jquery-1.8.3.min.js"></script> <script type="text/javascript" src="js/unslider.min.js"></script>
第2步:写HTML结构,即幻灯片列表
如果需要上一张下一张的翻页,才加上prev/next两个a对象。
<div class="banner"> <ul> <li><a href="#"><img src="images/1.jpg" /></a></li> <li><a href="#"><img src="images/2.jpg" /></a></li> <li><a href="#"><img src="images/3.jpg" /></a></li> </ul> <a href="#" class="unslider-arrow prev">Previous slide</a> <a href="#" class="unslider-arrow next">Next slide</a> </div>
第3步:添加css样式,这个样式当然是自己写,完全自定义,超棒。
.banner { position: relative; overflow: hidden;width:1200px;height:300px;margin:0 auto;cursor:pointer; } .banner ul li { float: left; } .banner ul li img{width:100%;display:block;} .dots{position:absolute;width:100%;bottom:20px;text-align:center;} .dot{ display:inline-block; width: 12px; height: 12px; font-size: 0px; line-height: 0px; margin-right: 12px; cursor: pointer; background-color: #ffffff; border-radius: 50%; } .dot.active{background-color: #5EB309;} .unslider-arrow{ position:absolute;width:80px;height:100%;top:0;font-size:0;text-indent:-999em;} .prev{ left:0; background:url(../images/left_arrow.svg) no-repeat center center;} .prev:hover{ background-image:url(../images/left_arrowhover.svg); } .next{ right:0; background:url(../images/right_arrow.svg) no-repeat center center;} .next:hover{ background-image:url(../images/right_arrowhover.svg);}
第4步:初始化插件,加入参数控制。
<script type="text/javascript"> $(function() { $('.banner').unslider({ speed: 500, // 播放速度,单位毫秒 delay: 3000, // 每张图片滑动的间隔时间,单位毫秒 keys: true, // 允许使用键盘的←、→两个键翻页,按ESC键可以停止自动播放。 dots: true, // 允许圆点导航 fluid: true // 支持响应式布局,随着设备的宽度变化自适应 }); //允许有上一张下一张翻页出现,才需要加下面的代码。 var unslider = $('.banner').unslider(); $('.unslider-arrow').click(function() { var fn = this.className.split(' ')[1]; // Either do unslider.data('unslider').next() or .prev() depending on the className unslider.data('unslider')[fn](); }); }); </script>
如果有兴趣可以参看源代码,这是第一版本的。
Unslider插件第一版源代码:
/** * Unslider by @idiot and @damirfoy * Contributors: * - @ShamoX * */ (function($, f) { var Unslider = function() { // 克隆对象 var _ = this; // 设置一些默认参数 _.o = { speed: 500, // 动画过渡的速度(毫秒),如果不需要过渡效果就设置为false delay: 3000, // 每张幻灯片的间隔时间(毫秒), 如果不是自动播放就设置为false init: 0, // 初始化延迟时间(毫秒),如果不需要延迟就设置为false pause: !f, // 当鼠标指针浮动在当前区域内时是否暂停自动播放 loop: !f, // 是否无尽循环播放 keys: f, // 是否开启键盘导航 dots: f, // 是否显示导航点 arrows: f, // 是否显示向前和向后的箭头 prev: '←', // 向前按钮中的显示文字(或html片段) next: '→', // 向后...... fluid: f, // 是否宽度自适应 starting: f, // 在每个动画前调用的函数 complete: f, // 在每个动画之后调用的函数 items: '>ul', // 幻灯片的容器选择器 item: '>li', // 需要滚动的选择器 easing: 'swing',// 动画的缓动函数(easing function) autoplay: true // 是否允许自动播放 }; _.init = function(el, o) { // 将我们在外部调用时设置的参数覆盖掉默认参数 _.o = $.extend(_.o, o); _.el = el; _.ul = el.find(_.o.items);//返回ul元素集合 _.max = [el.outerWidth() | 0, el.outerHeight() | 0];//保存一下幻灯片div容器的宽和高 _.li = _.ul.find(_.o.item).each(function(index) { var me = $(this), width = me.outerWidth(), height = me.outerHeight(); // 记录最大幻灯片的宽高 if (width > _.max[0]) _.max[0] = width; if (height > _.max[1]) _.max[1] = height; }); // 申请一些临时变量 var o = _.o, ul = _.ul, li = _.li, len = li.length;//li元素个数 // 当前索引,或者叫页码更容易理解吧,源代码中写了“Current indeed”,应该是“index”吧 _.i = 0; // 设置幻灯片div容器的样式,高度初始化为第一个li的高度 el.css({width: _.max[0], height: li.first().outerHeight(), overflow: 'hidden'}); // 设置ul元素的位置和宽度,宽度的公式是(li元素的个数乘以100)%,我的例子中就是300% ul.css({position: 'relative', left: 0, width: (len * 100) + '%'}); if(o.fluid) { li.css({'float': 'left', width: (100 / len) + '%'});//自适应宽度时,li元素的宽度就是把ul的宽度平均分成len份 } else { li.css({'float': 'left', width: (_.max[0]) + 'px'});//不是自适应时,li元素的宽度是最大的幻灯片的宽度 } // 在init毫秒后开启自动播放 o.autoplay && setTimeout(function() { if (o.delay | 0) { _.play(); if (o.pause) { el.on('mouseover mouseout', function(e) { _.stop();//鼠标经过时暂停 e.type == 'mouseout' && _.play();//鼠标离开时播放 }); }; }; }, o.init | 0); // 键盘事件处理 if (o.keys) { $(document).keydown(function(e) { var key = e.which; if (key == 37) _.prev(); // 左箭头按键 else if (key == 39) _.next(); // 右箭头按键 else if (key == 27) _.stop(); // Esc }); }; // 显示导航点 o.dots && nav('dot'); // 显示箭头 o.arrows && nav('arrow'); // 使幻灯片div容器宽度自适应 if (o.fluid) { $(window).resize(function() { _.r && clearTimeout(_.r); _.r = setTimeout(function() { var styl = {height: li.eq(_.i).outerHeight()}, width = el.outerWidth(); ul.css(styl); //这一串真是绕,其实就是计算div占父窗口的宽度原始比例,然后记录到styl中 styl['width'] = Math.min(Math.round((width / el.parent().width()) * 100), 100) + '%'; el.css(styl);//重新设置幻灯片div容器的宽度为比例而不是像素值,这样就能达到自适应的目的了 li.css({ width: width + 'px' });//设置li的绝对宽度,以防因div被自适应了而挤压或拉伸了li造成内容扭曲(如有误请大神指教) }, 50);//每次父窗口改变大小时,幻灯片div容器延迟50毫秒后再跟着自适应大小,请大神告诉我这样做的目的仅仅是为了效果更自然么 }).resize();//强制执行resize事件,使得自适应特性在最开始时就被设置好了 }; // 自定义move事件,这一段不太懂,求大神指点 if ($.event.special['move'] || $.Event('move')) { // 为幻灯片div元素绑定movestart、move、moveend事件 el.on('movestart', function(e) { if ((e.distX > e.distY && e.distX < -e.distY) || (e.distX < e.distY && e.distX > -e.distY)) { e.preventDefault();//鼠标位置不在当前区域时取消事件的默认动作(我猜的,关键是不知道distX这几个的准确含义) }else{ el.data("left", _.ul.offset().left / el.width() * 100); } }).on('move', function(e) { var left = 100 * e.distX / el.width(); var leftDelta = 100 * e.deltaX / el.width(); _.ul[0].style.left = parseInt(_.ul[0].style.left.replace("%", ""))+leftDelta+"%"; _.ul.data("left", left); }).on('moveend', function(e) { var left = _.ul.data("left");// if (Math.abs(left) > 30){ var i = left > 0 ? _.i-1 : _.i+1; if (i < 0 || i >= len) i = _.i; _.to(i); }else{ _.to(_.i); } }); }; return _; }; // 播放指定索引的幻灯片 _.to = function(index, callback) { if (_.t) { _.stop(); _.play(); } var o = _.o, el = _.el, ul = _.ul, li = _.li, current = _.i, target = li.eq(index); //在动画之前执行的函数,我的例子里都没有,可以忽略它们 $.isFunction(o.starting) && !callback && o.starting(el, li.eq(current)); // 如果(一张幻灯片也没有或者索引无效),并且不是循环播放,就啥也不做,我觉得这样不好,因为to这个函数就只能在循环播放状态下工作了 if ((!target.length || index < 0) && o.loop == f) return; // 检查索引是否有效,超出时设置为0,即第一张幻灯片 if (!target.length) index = 0; if (index < 0) index = li.length - 1;//索引负数时设置为最后一张幻灯片 target = li.eq(index);//获取目标元素 var speed = callback ? 5 : o.speed | 0,//执行回调函数后返回的是真则speed设为5,如果没有回调函数或返回假则设置为o.speed easing = o.easing, obj = {height: target.outerHeight()}; if (!ul.queue('fx').length) {//确保没有为ul元素添加函数队列,应该是为了防止上一次动作还没有完成吧 // 设置对应导航点的高亮 el.find('.dot').eq(index).addClass('active').siblings().removeClass('active'); // 改变幻灯片div容器的高度为目标元素的高度,并把ul的位置向左移动(index*100%),使目标元素正好在幻灯片div容器区域 el.animate(obj, speed, easing) && ul.animate($.extend({left: '-' + index + '00%'}, obj), speed, easing, function(data) { _.i = index;//移动结束之后更新一下当前索引 //动画结束之后执行的函数,我的例子中也没有,忽略它们 $.isFunction(o.complete) && !callback && o.complete(el, target); }); }; }; // 每隔delay毫秒自动播放 _.play = function() { _.t = setInterval(function() { _.to(_.i + 1);//这里就加了1个索引号,具体的处理都封装在了to方法中 }, _.o.delay | 0); }; // 停止自动播放 _.stop = function() { _.t = clearInterval(_.t); return _; }; // 向后翻一张 _.next = function() { return _.stop().to(_.i + 1); }; // 向前翻一张 _.prev = function() { return _.stop().to(_.i - 1); }; // 创建导航点和箭头 function nav(name, html) { if (name == 'dot') { html = '<ol class="dots">'; $.each(_.li, function(index) { html += '<li class="' + (index == _.i ? name + ' active' : name) + '">' + ++index + '</li>'; }); html += '</ol>'; /*整理一下,在我的例子中就是这副摸样 <ol class="dots"> <li class="dot active">0</li> <li class="dot">1</li> <li class="dot">2</li> </ol> */ } else { html = '<div class="'; html = html + name + 's">' + html + name + ' prev">' + _.o.prev + '</div>' + html + name + ' next">' + _.o.next + '</div></div>'; /*也整理一下 <div class="arrows"> <div class="arrow prev">←</div> <div class="arrow next">→</div> </div> */ }; //先给幻灯片div容器元素加上has-dots或arrows的class,再把上面组织好的元素追加为子元素,并给该子元素添加click事件处理函数 _.el.addClass('has-' + name + 's').append(html).find('.' + name).click(function() { var me = $(this); me.hasClass('dot') ? _.stop().to(me.index()) : me.hasClass('prev') ? _.prev() : _.next(); }); }; }; // 将unslider方法扩展到jQuery对象,使任意jQuery对象都能够直接访问该方法,就像上面那样:$('.banner').unslider(); $.fn.unslider = function(o) { var len = this.length; // 遍历li元素集 return this.each(function(index) { var me = $(this), key = 'unslider' + (len > 1 ? '-' + ++index : ''), instance = (new Unslider).init(me, o); // 给div元素添加数据 me.data(key, instance).data('key', key); }); }; Unslider.version = "1.0.0"; })(jQuery, false);
不过我试了一下,如果幻灯片图片比较少,不停的就两张图片滑来滑去,效果很单调,所以这个插件适合图片比较多的时候。
发表评论:
◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。