基于jquery的图片轮播 tab切换组件


Posted in Javascript onJuly 19, 2012

目前只添加了scroll和none的效果,scroll即滑动的效果,可以支持x和y方向的滑动;none就是没有任何效果,只是显示和隐藏,后续需要添加其他效果再做扩展,写的有点水,呵呵,在此留笔,防止丢失。

Demo Address:http://demo.3water.com/js/2012/sinaapp/

/** 
* 巨无霸轮播 
*/ 
$.fn.loopSlider = function(option) { 
var setting = { 
// 默认显示的顺序 
initIndex: 1, 
// 加在title节点上的样式 
className: "current", 
// 轮播方向,默认为x轴方向轮播 
direct: "x", 
// 上一张按钮 
prevBtn: "", 
// 下一张按钮 
nextBtn: "", 
// 上下翻页按钮禁用的样式 
btnDisable: "disable", 
// 按钮按下的样式 
btnTouchClass: "", 
// 自动轮播 
auto: false, 
// 自动轮播时间间隔 
timeFlag: 4000, 
// 轮播效果时间 
scrollTime: 350, 
// 轮播效果 
effect: "scroll", 
// 在只有一个轮播元素的时候是否隐藏滑动按钮 
hideBtn: true, 
// 是否循环轮播 
cycle: true, 
// 轮播的内容区的容器路径 
contentContainer: "#imgScroll", 
// 轮播的内容区的节点 
contentChildTag: "li", 
// 标题轮播区域的容器路径 
titleContainer: "#titleScroll", 
// 标题轮播区域的节点 
titleChildTag: "li", 
// 轮播的内容区的数组 
cont: [], 
// 轮播的标题区的数组 
tabs: [], 
// 当前轮播序号 
current: 0, 
// 定时器 
ptr: "", 
// 轮播回调函数,每次轮播调用,参数为当前轮播的序号 
callback: function() { 
return true; 
} 
} 
if (option) { 
$.extend(setting, option); 
} 
// 初始化当前调用类型的函数 
setting.currentMethod = function() { 
return true; 
} 
var boss = $(this); 
// 如果不是第一个元素先轮播 
if (setting.initIndex != 1) { 
setting.current = setting.initIndex - 1; 
} 
// 获取轮播的节点列表 
var childList = boss.find(setting.contentContainer + " " + setting.contentChildTag); 
// 获取轮播标题节点列表 
var titleList = boss.find(setting.titleContainer + " " + setting.titleChildTag); 
// 保存内容区每一个轮播节点 
setting.cont = childList; 
// 保存标题的轮播节点 
setting.tabs = titleList; 
// 如果没有需要轮播的内容,直接返回 
if (setting.cont.length == 0) { 
return; 
} 
// 给内容区和标题区设置index属性 
childList.each(function(index) { 
$(this).attr("index", index); 
titleList.eq(index).attr("index", index); 
}); 
// 上下箭头 
var nextBtn = boss.find(setting.nextBtn); 
var prevBtn = boss.find(setting.prevBtn); 
// 长度 
var counts = childList.length; 
// 轮播容器的父节点 
var childParent = childList.parent(); 
var titleParent = titleList.parent(); 
if (childList.length < setting.initIndex) { 
setting.current = 0; 
} 
// 初始化 
doInit(); 
if (childList.length <= 1) { 
return; 
} 
/** 
* 处理无效果的切换 
*/ 
var doScrollNone = { 
process: function(i) { 
childList.eq(i).css("display", "block").siblings().css("display", "none"); 
titleList.eq(i).addClass(setting.className).siblings().removeClass(setting.className); 
// 记录当前显示的节点 
setting.current = i; 
// 调用回调函数 
setting.callback(setting.current); 
}, 
init: function() { 
setting.currentMethod = doScrollNone; 
bindEvent(); 
// 自动轮播 
if (setting.auto) { 
processAuto(); 
} 
// 初始化的时候也调用回调函数 
setting.callback(setting.current); 
} 
}; 
var doScrollXY = { 
c_width: 0, 
c_height: 0, 
init: function() { 
// 轮播元素的宽度 
this.c_width = childList.width(); 
// 轮播元素的高度 
this.c_height = childList.height(); 
// x轴方向轮播 
if (setting.direct == "x") { 
childParent.width(this.c_width * (childList.length > 1 ? counts + 1 : counts)); 
childParent.css("left", -this.c_width * (setting.current)); 
} else { 
childParent.height(this.c_height * (childList.length > 1 ? counts + 1 : counts)); 
childParent.css("top", -this.c_height * (setting.current)); 
} 
titleList.eq(setting.current).addClass(setting.className).siblings().removeClass(setting.className); 
setting.currentMethod = doScrollXY; 
// 绑定事件 
bindEvent(); 
// 初始化的时候也调用回调函数 
setting.callback(setting.current); 
// 自动轮播 
if (setting.auto) { 
processAuto(); 
} 
}, 
process: function(i, needFast) { 
setting.current = i; 
//alert(i) 
if (setting.direct == "x") { 
// 执行效果动画 
childParent.animate({ 
left: "-" + (this.c_width * i) 
}, 
(needFast ? 50 : setting.scrollTime), 
function() { 
if (setting.current == counts) { 
doScrollXY.processMove("left", $(this)); 
} 
if (setting.auto) { 
processAuto(); 
} 
}); 
} else { 
childParent.animate({ 
top: "-" + (this.c_height * i) 
}, 
(needFast ? 50 : setting.scrollTime), 
function() { 
if (setting.current == counts) { 
doScrollXY.processMove("top", $(this)); 
} 
if (setting.auto) { 
processAuto(); 
} 
}); 
} 
if (i == counts) { 
i = 0; 
} 
// 调用回调函数 
setting.callback(setting.current); 
titleList.eq(i).addClass(setting.className).siblings().removeClass(setting.className); 
}, 
processMove: function(direct, node) { 
var childs = node.children(); 
for (var i = 1; i < childs.length - 1; i++) { 
var removeNode = childs.eq(i).remove(); 
node.append(removeNode); 
} 
var first = childs.eq(0).remove(); 
node.append(first); 
node.css(direct, "0"); 
} 
}; 
switch (setting.effect) { 
case "none": 
doScrollNone.init(); 
break; 
case "scroll": 
doScrollXY.init(); 
break; 
} 
// 一些初始化操作 
function doInit() { 
childParent.css("position", "relative"); 
if (!setting.cycle) { 
prevBtn.removeClass(setting.btnDisable); 
nextBtn.removeClass(setting.btnDisable); 
if (setting.current == 0) { 
prevBtn.addClass(setting.btnDisable); 
} 
if (setting.current == counts - 1) { 
nextBtn.addClass(setting.btnDisable); 
} 
} 
// 只有一个元素,并且需要隐藏按钮 
if (childList.length <= 1 && setting.hideBtn) { 
prevBtn.hide(); 
nextBtn.hide(); 
} 
// 克隆第一个元素到最后 
if (childList.length > 1) { 
var cloneNode = childList.eq(0).clone(); 
cloneNode.attr("index", counts); 
cloneNode.appendTo(childParent); 
} 
} 
/** 
* 绑定轮播事件 
*/ 
function bindEvent() { 
nextBtn && nextBtn.bind("click", 
function(event) { 
// 如果按钮已经被禁用 
if ($(this).hasClass(setting.btnDisable)) { 
return; 
} 
var cur = setting.current; 
if (cur >= 0) { 
prevBtn.removeClass(setting.btnDisable); 
} 
if (cur == counts - 2 && !setting.cycle) { 
$(this).addClass(setting.btnDisable); 
} 
if (cur == counts) { 
setting.current = 1; 
} else if (cur == counts - 1) { 
// 轮播到最后一个 
setting.current = counts; 
} else { 
setting.current = cur + 1; 
} 
if (setting.ptr) { 
clearInterval(setting.ptr); 
setting.ptr = null; 
} 
$(this).addClass(setting.btnTouchClass); 
setting.currentMethod.process(setting.current); 
}); 
prevBtn && prevBtn.bind("click", 
function() { 
if ($(this).hasClass(setting.btnDisable)) { 
return; 
} 
var cur = setting.current; 
if (cur <= counts - 1) { 
nextBtn.removeClass(setting.btnDisable); 
} 
if (cur == 1 && !setting.cycle) { 
$(this).addClass(setting.btnDisable); 
} 
setting.current = cur == 0 ? counts - 1 : cur - 1; 
if (setting.ptr) { 
clearInterval(setting.ptr); 
setting.ptr = null; 
} 
$(this).addClass(setting.btnTouchClass); 
var fast = false; 
if (cur == 0) { 
fast = true; 
} 
setting.currentMethod.process(setting.current, fast); 
}); 
titleParent && titleParent.bind("click", 
function(e) { 
var element = $(e.target); 
// 得到轮播节点 
while (element[0].tagName != titleList[0].tagName) { 
element = element.parent(); 
} 
if (setting.ptr) { 
clearInterval(setting.ptr); 
setting.ptr = null; 
} 
var index = parseInt(element.attr("index"), 10); 
if (index != 0) { 
prevBtn.removeClass(setting.btnDisable); 
} else if (!setting.cycle) { 
prevBtn.addClass(setting.btnDisable); 
} 
if (index != counts - 1) { 
nextBtn.removeClass(setting.btnDisable); 
} else if (!setting.cycle) { 
nextBtn.addClass(setting.btnDisable); 
} 
setting.currentMethod.process(index); 
}); 
childParent[0].ontouchstart = handleTouchStart; 
// 触摸屏幕事件 
function handleTouchStart(event) { 
var element = $(event.target); 
// 得到标题节点 
while (element[0].tagName != childList[0].tagName) { 
element = element.parent(); 
} 
if (event.targetTouches.length == 0) { 
return; 
} 
var touch = event.targetTouches[0]; 
var startX = touch.pageX; 
var startY = touch.pageY; 
var moveDirect = ""; 
var currentPosition = setting.direct == "x" ? childParent.css("left") : childParent.css("top"); 
if (setting.ptr) { 
clearInterval(setting.ptr); 
setting.ptr = null; 
} 
// 手指滑动事件 
childParent[0].ontouchmove = handleTouchMove; 
function handleTouchMove(moveEvent) { 
var movetouch = moveEvent.targetTouches[0]; 
if (setting.direct == 'x') { 
var moveX = movetouch.pageX; 
var moveY = movetouch.pageY; 
var x = moveX - startX; 
var y = moveY - startY; 
// 这里的目的是在左右滑动图片的时候,阻止浏览器的默认事件,但是如果是上下滑动的情况,一般是滑动滚动条,不能直接就阻止浏览器默认事件,不然会导致用户在上下滑动的时候页面停止的情况,这里设置的是在x轴方向要比在Y轴方向滑动至少多10的像素,可以有效的避免上述情况发生 
if (Math.abs(x) - Math.abs(y) > 10) { 
// 阻止默认的事件 
moveEvent.preventDefault(); 
childParent.css("left", parseFloat(currentPosition) + x); 
moveDirect = x > 0 ? "sub": "add"; 
} else { 
return; 
} 
} else { 
// Y轴方向滚动 
moveEvent.preventDefault(); 
var moveY = touch.pageY; 
var y = moveY - startY; 
childParent.css("top", parseFloat(currentPosition) + y); 
moveDirect = y > 0 ? "sub": "add"; 
} 
childParent[0].ontouchend = handleTouchEnd; 
} 
//手指离开屏幕 
function handleTouchEnd() { 
//根据手指移动的方向,判断下一个要显示的节点序号 
var fast = false; 
if (moveDirect == "add") { 
if (setting.current == counts) { 
setting.current = 1; 
} else { 
setting.current = setting.current + 1; 
} 
} else { 
if (setting.current == 0) { 
setting.current = counts - 1; 
fast = true; 
} else { 
setting.current = setting.current - 1; 
} 
} 
// 调用对应的处理函数 
setting.currentMethod.process(setting.current, fast); 
childParent[0].ontouchend = null; 
childParent[0].ontouchmove = null; 
} 
} 
} 
/** 
* 自动轮播 
*/ 
function processAuto() { 
if (setting.ptr) { 
clearInterval(setting.ptr); 
setting.ptr = null; 
} 
// 设置轮播定时器 
setting.ptr = setInterval(function() { 
if (setting.current == counts) { 
setting.current = 1; 
} else if (setting.current == counts - 1) { 
// 轮播到最后一个 
setting.current = counts; 
} else { 
setting.current = setting.current + 1; 
} 
var index = setting.current; 
if (index != 0) { 
prevBtn.removeClass(setting.btnDisable); 
} else if (!setting.cycle) { 
prevBtn.addClass(setting.btnDisable); 
} 
if (index != counts - 1) { 
nextBtn.removeClass(setting.btnDisable); 
} else if (!setting.cycle) { 
nextBtn.addClass(setting.btnDisable); 
} 
setting.currentMethod.process(setting.current); 
}, 
setting.timeFlag); 
} 
// 返回一个函数,可以在调用返回函数,指定下一次需要轮播的图片的序号,一般用在点击一个小图,然后需要查看大图的情况下,那么就只需要给大图绑定一次轮播事件,再点击某一张小图的时候只需要调用该函数,把对应的序号传入即可 
return function(index) { 
if (index < 0) { 
index = 0; 
} else if (index >= counts) { 
index = counts - 1; 
} 
setting.currentMethod.process(index); 
} 
}
Javascript 相关文章推荐
服务端 VBScript 与 JScript 几个相同特性的写法 By shawl.qiu
Mar 06 Javascript
表格 隔行换色升级版
Nov 07 Javascript
javascript当onmousedown、onmouseup、onclick同时应用于同一个标签节点Element
Jan 05 Javascript
js获取和设置属性的方法
Feb 20 Javascript
Windows 系统下安装和部署Egret的开发环境
Jul 31 Javascript
包含中国城市的javascript对象实例
Aug 03 Javascript
jQuery手动点击实现图片轮播特效
Apr 20 Javascript
Javascript中的Prototype到底是什么
Feb 16 Javascript
js实现悬浮窗效果(支持拖动)
Mar 09 Javascript
js和jquery中获取非行间样式
May 05 jQuery
详解小程序开发经验:多页面数据同步
May 18 Javascript
js实现for循环跳过undefined值示例
Jul 02 Javascript
JavaScript面向对象知识串结(读JavaScript高级程序设计(第三版))
Jul 17 #Javascript
JavaScript面向对象(极简主义法minimalist approach)
Jul 17 #Javascript
基于jQuery的获取标签名的代码
Jul 16 #Javascript
写自已的js类库需要的核心代码
Jul 16 #Javascript
js不完美解决click和dblclick事件冲突问题
Jul 16 #Javascript
js jquery数组介绍
Jul 15 #Javascript
js限制文本框只能输入数字(正则表达式)
Jul 15 #Javascript
You might like
Windows下PHP5和Apache的安装与配置
2006/09/05 PHP
关于PHP的相似度计算函数:levenshtein的使用介绍
2013/04/15 PHP
thinkphp中的url跳转用法分析
2016/07/12 PHP
php利用递归实现删除文件目录的方法
2016/09/23 PHP
PHPStrom 新建FTP项目以及在线操作教程
2016/10/16 PHP
简单谈谈 php 文件锁
2017/02/19 PHP
PHP简单获取上月、本月、近15天、近30天的方法示例
2017/07/03 PHP
遨游,飞飞,IE,空中网 浏览器无提示关闭方法
2011/07/11 Javascript
jquery如何判断表格同一列不同行input数据是否重复
2014/05/14 Javascript
js数组与字符串的相互转换方法
2014/07/09 Javascript
使用命令对象代替switch语句的写法示例
2015/02/28 Javascript
javascript中的Function.prototye.bind
2015/06/25 Javascript
js生成随机数的过程解析
2015/11/24 Javascript
js获取当前年月日-YYYYmmDD格式的实现代码
2016/06/01 Javascript
JS简单实现DIV相对于浏览器固定位置不变的方法
2016/06/17 Javascript
微信小程序技巧之show内容展示,上传文件编码问题
2017/01/23 Javascript
Vue中v-show添加表达式的问题(判断是否显示)
2018/03/26 Javascript
Vue实现剪贴板复制功能
2019/12/31 Javascript
Vue3 响应式侦听与计算的实现
2020/11/11 Javascript
Python字符串详细介绍
2015/05/09 Python
Python读写配置文件的方法
2015/06/03 Python
Python内置函数OCT详解
2016/11/09 Python
基于随机梯度下降的矩阵分解推荐算法(python)
2018/08/31 Python
pycharm重置设置,恢复默认设置的方法
2018/10/22 Python
Python hashlib加密模块常用方法解析
2019/12/18 Python
Pytorch根据layers的name冻结训练方式
2020/01/06 Python
借助Paramiko通过Python实现linux远程登陆及sftp的操作
2020/03/16 Python
jupyter lab文件导出/下载方式
2020/04/22 Python
2014乡镇领导班子四风对照检查材料思想汇报
2014/10/05 职场文书
领导干部群众路线教育实践活动剖析材料
2014/10/10 职场文书
酒店财务经理岗位职责
2015/04/08 职场文书
生死抉择观后感
2015/06/09 职场文书
2016年父亲节寄语
2015/12/04 职场文书
导游词之北京明十三陵
2019/10/28 职场文书
在K8s上部署Redis集群的方法步骤
2021/04/27 Redis
react中props 的使用及进行限制的方法
2021/04/28 Javascript