轮播的实现方式
1.闪现方式的轮播
不论述,实现比较简单,效果也比较好
2.滑动轮播
以下面的html代码为例(向左滑动)
<div class="example" style="overflow: hidden; width: 266px;"> <ul style="width: 798px; float: left; height: 216px; margin-left: 0px;"> <li style="width: 266px; float: left; height: 216px;"></li> <li style="width: 266px; float: left; height: 216px;"></li> <li style="width: 266px; float: left; height: 216px;"></li> </ul> </div>
插件源码:实现向左和向上轮播,手动切换也是向左和向上切换(手动切换关键源码)
var all = $panel.find('>li'), prevAll = new Array(); prevAll[0] = all.eq(0); //将目标节点前的所有节点都保存到prevAll中,动画结束后将这些节点一一按顺序加到容器的后面 for(var i = 1; i < len; i++){ all.eq(i).css({display: 'none'}); prevAll[i] = all.eq(i); } ... $panel.animate({ 'marginLeft': -options.width + 'px' }, options.duration, function() { for(var i = 0; i < prevAll.length; i++){ $panel.append($(prevAll[i]).css({display: 'block'})); //将当前展示节点前的所有节点都加载到最后 } $panel.css({ marginLeft: 0 }); })
滑动轮播的实现方式主要有两种
1)切换父元素margin-left,将第一个子元素不断添加到父容器结尾
简单实现
var $panel = $('example'); var scrollTimer = setInterval(function() { scrollNews($panel); }, 3000); function $scrollNews(){ $panel.animate({ 'marginLeft': '-266px' }, 500, function() { $panel.css({ marginLeft: 0 }).find('>li:first').appendTo($panel); }) }
这种方式有一个问题就是在老IE上可能存在兼容问题。
2) 累计方式设置父元素margin-left
不过在margin-left设置到最小的时候(滑动到最后一个元素),将第一个子元素的位置设置为最后一个子元素的后面,当最后一个元素滚动到第一个元素后,父元素margin-left置为0且第一个子元素的位置归位。举个简单代码例子
var $panel = $('.example'), index = 0; var scrollTimer = setInterval(function() { scrollNews($panel); }, 3000); function scrollNews(){ if(++index >= 2){ $panel.css({ 'paddingLeft': 266 + 'px' }) $panel.find('>li:first').css({ 'position': 'absolute', 'left': 266*index + 'px' }); } $panel.animate({ 'marginLeft': -266*index + 'px' }, 500, function() { if(++index > 3){ $panel.css({ marginLeft: 0 }); } if(index >= 3){ index = 0; $panel.css({ marginLeft: 0, 'paddingLeft': 0 }); $panel.find('>li:first').css({ 'position': 'static', 'left': 'auto' }); } }) }
更复杂的滚动插件需要支持水平和垂直方向的滚动(四个方向)、可以手动切换焦点、可以翻上一个下一个。附上本人写完整的插件源码
插件源码jquery.nfdscroll.js:支持水平和垂直方向(四个方向)滚动,手动切换会随切换方向滚动
/** * @author '陈桦' * @date '2016-5-10' * @description 滑动轮播插件,支持水平和垂直方向滑动轮播 * * @example html: <style type="text/css"> body,ul,ol{margin: 0; padding: 0;} ul,ol{list-style: none;} .li1{background-color: #000;} .li2{background-color: #333;} .li3{background-color: #666;} .li4{background-color: #999;} .example{margin-left: 300px;} .example ol { position: absolute; padding-left: 80px; width: 186px; height: 20px; top: 186px; left: 0px; background: #fff; cursor: pointer; } ol li{ float: left; width: 10px; height: 10px; margin: 5px; background: #ff0; border-radius: 10px; } ol li.circle{ background: #f00; } </style> <div class="example"> <!-- 滚动内容ul --> <ul> <li class="li1"><a href="xxx" target="_blank" title="xxx"></a></li> <li class="li2"><a href="xxx" target="_blank" title="xxx"></a></li> <li class="li3"><a href="xxx" target="_blank" title="xxx"></a></li> <li class="li4"><a href="xxx" target="_blank" title="xxx"></a></li> </ul> <!-- 焦点列表,可选 --> <ol> <li class=""></li> <li class=""></li> <li class=""></li> <li class=""></li> </ol> <!-- 上一个和下一个,可选 --> <div> <a class="nfdscroll-prev" href="javascript:void(0);"></a> <a class="nfdscroll-next" href="javascript:void(0);"></a> </div> </div> js: $('.example').nfdscroll({ startIndex:0, width:'266', height:'216', interval:2000, selected:'circle', prevText:'上一个', nextText:'下一个', deriction:'left', callback: function(index,$currentNode){ console.log(index) } }); * @example end * @param startIndex {Number} 默认从第几个滚动体开始滚动,可选(0-n,0表示第一个,默认为0) * @param width {Number} 滚动体宽度,可选(当宽度为0时表示不设置宽度) * @param height {Number} 滚动体高度,可选(当高度为0时表示不设置高度) * @param interval {Number} 间隔时间,单位毫秒, 当值为负时表示不进行自动滚动 * @param duration {Number} 动画持续时间 * @param selected {String} 滚动切换小图标(焦点列表)当前class * @param deriction {String} 滚动方向,支持left/right和top/bottom * @param callback {Function} 滑动动画结束时触发的回调,参数(index,$currentNode),index:轮播结束后展示的节点的索引;currentNode:轮播结束后当前展示的节点的jquery对象 * @param prevText {String} 上一个按钮的文本,默认是"上一个" * @param nextText {String} 下一个按钮的文本,默认是"下一个" */ jQuery.fn.extend({ nfdscroll: function(options) { var defaultOpt = { startIndex: 0, width: 0, //滚动体宽度,可选(当宽度为0时表示不设置宽度) height: 0, //滚动体高度,可选(当高度为0时表示不设置高度度) interval: 1000, //间隔时间毫秒 duration: 400, //动画持续时间 selected: 'selected', //滚动切换小图标当前class prevText: '上一个', nextText: '下一个', deriction: 'left', //滚动方向 callback: function(index, $currentNode) { //每次滚动到新节点后马上触发,currentNode是当前展示的节点的jquery对象 } }, $this = this, $panel = $this.find('>ul'), //滚动容器 $panelList = $panel.find('>li'), $selectList = $this.find('>ol>li'), //选择容器 options = jQuery.extend(defaultOpt, options), animateFn, //滚动动画 max = $panel.find(">li").length, //要滚动的节点的数量 focusIndex = 0, //当前展示的节点的索引 nfdscrollTimer = 0, //计时器 inAnimation = false, //动画过程中不再响应其他动画 isWaitting = false, //是否有未执行的等待动画 waittingIndex; //未执行的等待动画的目标index $this.find('.nfdscroll-prev').text(options.prevText); $this.find('.nfdscroll-next').text(options.nextText); //只有一个展示,不需要轮播 if ($panelList.length <= 1) { return; } //当前动画没有做完但是焦点已经切换到下一个地方,这个函数就是用来执行保障当前显示的页面和鼠标指定的目标一致的处理 function doWaitting() { if (isWaitting) { startScroll(waittingIndex); } } //开始轮播 function startScroll(toIndex) { stopScroll(); if (inAnimation) { isWaitting = true; waittingIndex = toIndex; return; //动画过程中不再响应其他动画 } else { isWaitting = false; } if (toIndex == undefined) { if (options.interval > 0) { nfdscrollTimer = setInterval(function() { animateFn(toIndex); }, options.interval); } //跳到指定index后再计时 } else { animateFn(toIndex); if (options.interval > 0) { nfdscrollTimer = setInterval(function() { animateFn(); }, options.interval); } } } //停止轮播 function stopScroll() { clearInterval(nfdscrollTimer); } //向左向右滚动动画 //参数toIndex: number,滚动到指定index function leftRightAnimate(toIndex) { //默认滚动方式 if (toIndex == undefined) { if (options.deriction == 'left') { toIndex = focusIndex + 1; } else { toIndex = focusIndex - 1; } } if (toIndex != focusIndex) { inAnimation = true; //当前为最后一个轮播体时的处理 var tInd = 0; if (toIndex >= max) { //最后一张图片继续滚动时 $panel.css({ 'paddingLeft': options.width + 'px' }) $panelList.eq(0).css({ 'position': 'absolute', 'left': options.width * toIndex + 'px' }); tInd = 0; } else if (toIndex < 0) { //仅仅在当前图片是第一个图片,然后点击上一个图片的时候出现 //当前为最后一个轮播体时的处理 $panelList.eq(max - 1).css({ 'position': 'absolute', 'left': -options.width + 'px' }); tInd = max - 1; } else { tInd = toIndex; } //先将焦点切换过去 $selectList.filter('.' + options.selected).removeClass(options.selected) .end().eq(tInd).addClass(options.selected); $panel.animate({ 'marginLeft': -options.width * toIndex + 'px' }, options.duration, function() { focusIndex = tInd; if (toIndex >= max) { //最后一张图片继续滚动时 $panel.css({ 'marginLeft': 0, 'paddingLeft': 0 }); $panelList.eq(0).css({ 'position': 'static', 'left': 'auto' }); } else if (toIndex < 0) { //仅仅在当前图片是第一个图片,然后点击上一个图片的时候出现 $panel.css({ 'marginLeft': -options.width * focusIndex + 'px', 'paddingLeft': 0 }); $panelList.eq(max - 1).css({ 'position': 'static', 'left': 'auto' }); } options.callback(focusIndex, $panelList.eq(focusIndex)); inAnimation = false; doWaitting(); }) } } //向上向下滚动动画 function topBottomAnimate(toIndex) { //默认滚动方式 if (toIndex == undefined) { if (options.deriction == 'top') { toIndex = focusIndex + 1; } else { toIndex = focusIndex - 1; } } if (toIndex != focusIndex) { inAnimation = true; //当前为最后一个轮播体时的处理 var tInd = 0; if (toIndex >= max) { $panel.css({ 'paddingTop': options.height + 'px' }) $panelList.eq(0).css({ 'position': 'absolute', 'top': options.height * toIndex + 'px' }); tInd = 0; } else if (toIndex < 0) { //仅仅在当前图片是第一个图片,然后点击上一个图片的时候出现 //当前为最后一个轮播体时的处理 $panelList.eq(max - 1).css({ 'position': 'absolute', 'top': -options.height + 'px' }); tInd = max - 1; } else { tInd = toIndex; } //先将焦点切换过去 $selectList.filter('.' + options.selected).removeClass(options.selected) .end().eq(tInd).addClass(options.selected); $panel.animate({ 'marginTop': -options.height * toIndex + 'px' }, options.duration, function() { focusIndex = tInd; if (toIndex >= max) { $panel.css({ marginTop: 0, 'paddingTop': 0 }); $panelList.eq(0).css({ 'position': 'static', 'top': 'auto' }); } else if (toIndex < 0) { //仅仅在当前图片是第一个图片,然后点击上一个图片的时候出现 $panel.css({ 'marginTop': -options.height * focusIndex + 'px', 'paddingTop': 0 }); $panelList.eq(max - 1).css({ 'position': 'static', 'top': 'auto' }); } options.callback(focusIndex, $panelList.eq(focusIndex)); inAnimation = false; doWaitting(); }) } } function bindEvent() { //绑定事件 $this.on('mouseover', function() { stopScroll(); }).on('mouseout', function() { startScroll(); }).on('click', '.nfdscroll-prev', function() { stopScroll(); startScroll(focusIndex - 1); }).on('click', '.nfdscroll-next', function() { stopScroll(); startScroll(focusIndex + 1); }) $selectList.on('mouseover', function() { stopScroll(); if (!$(this).is('.' + options.selected)) { startScroll($(this).index()); } }); } function init() { $this.css({ position: 'relative', overflow: 'hidden' }); $panel.css({ position: 'relative' }) focusIndex = options.startIndex; //默认从startIndex开始滚动 $selectList.eq(focusIndex).addClass(options.selected); //先将焦点切换过去 if (options.deriction == 'left' || options.deriction == 'right') { //初始化样式,实际上不应该插件里面来做样式,应该使用者自己就保证样式没有问题 var cssO = { width: options.width, 'float': 'left' } $this.css({ width: options.width }); //只需要管宽度即可 if (options.height) { cssO.height = options.height; } var leng = $panel.find('>li').css(cssO).length; $panel.css({ width: options.width * leng + 'px', 'marginLeft': -options.width * focusIndex + 'px' }); animateFn = leftRightAnimate; } else if (options.deriction == 'top' || options.deriction == 'bottom') { var cssO = { height: options.height } $this.css({ height: options.height }); //只需要管高度度即可 if (options.width) { cssO.width = options.width; } var leng = $panel.find('>li').css(cssO).length; $panel.css({ height: options.height * leng + 'px', 'marginTop': -options.height * focusIndex + 'px' }); animateFn = topBottomAnimate; } else { alert('插件只支持left/right/top/bottom四种方向上的滚动'); return; } startScroll(); } bindEvent(); init(); return { 'stopScroll': stopScroll, 'startScroll': startScroll } } });
一个完整的例子
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>轮播测试例子</title> <style type="text/css"> body,ul,ol{margin: 0; padding: 0;} ul,ol{list-style: none;} .li1{background-color: #000;} .li2{background-color: #333;} .li3{background-color: #666;} .li4{background-color: #999;} .example{margin-left: 300px;} .example ol { position: absolute; padding-left: 80px; width: 186px; height: 20px; top: 186px; left: 0px; background: #fff; cursor: pointer; } ol li{ float: left; width: 10px; height: 10px; margin: 5px; background: #ff0; border-radius: 10px; } ol li.circle{ background: #f00; } </style> </head> <body> <div class="example"> <!-- 滚动内容ul --> <ul> <li class="li1"><a href="xxx" target="_blank" title="xxx"></a></li> <li class="li2"><a href="xxx" target="_blank" title="xxx"></a></li> <li class="li3"><a href="xxx" target="_blank" title="xxx"></a></li> <li class="li4"><a href="xxx" target="_blank" title="xxx"></a></li> </ul> <!-- 焦点列表,可选 --> <ol> <li class=""></li> <li class=""></li> <li class=""></li> <li class=""></li> </ol> <!-- 上一个和下一个,可选 --> <div> <a class="nfdscroll-prev" href="javascript:void(0);"></a> <a class="nfdscroll-next" href="javascript:void(0);"></a> </div> </div> <script type="text/javascript" src="common/jquery.js"></script> <script type="text/javascript" src="common/jquery.nfdscroll.js"></script> <script type="text/javascript"> $('.example').nfdscroll({ startIndex:0, width:'266', height:'216', interval: 2000, selected:'circle', prevText:'上一个', nextText:'下一个', deriction:'left', callback: function(index,$currentNode){ console.log(index) } }); </script> </body> </html>
实现的效果
里面ol、nfdscroll-prev等的样式自己手动调整