基于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 相关文章推荐
用Javascript读取中文COOKIE的解决办法
Feb 15 Javascript
javascript 异步页面查询实现代码(asp.net)
May 26 Javascript
jQuery 中使用JSON的实现代码
Dec 01 Javascript
自己使用jquery写的一个无缝滚动的插件
Apr 30 Javascript
node.js中的fs.rmdirSync方法使用说明
Dec 16 Javascript
谈一谈javascript闭包
Jan 28 Javascript
JS判断图片是否加载完成方法汇总(最新版)
May 13 Javascript
js 判断数据类型的几种方法
Jan 13 Javascript
JavaScript实现垂直滚动条效果
Jan 18 Javascript
windows下更新npm和node的方法
Nov 30 Javascript
JavaScript fetch接口案例解析
Aug 30 Javascript
JS用最简单的方法实现四舍五入
Aug 27 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
咖啡风味 世界咖啡主要分布分布 咖啡的生长要求
2021/03/06 新手入门
Win9x/ME下Apache+PHP安装配置
2006/10/09 PHP
php+iframe实现隐藏无刷新上传文件
2012/02/10 PHP
php分页原理 分页代码 分页类制作教程
2016/09/23 PHP
PHP常见字符串处理函数用法示例【转换,转义,截取,比较,查找,反转,切割】
2016/12/24 PHP
javascript 面向对象编程基础 多态
2009/08/21 Javascript
Jquery+ajax请求data显示在GridView上(asp.net)
2010/08/27 Javascript
js jq 单击和双击区分示例介绍
2013/11/05 Javascript
jQuery Migrate 1.1.0 Released 注意事项
2014/06/14 Javascript
Jquery焦点图实例代码
2014/11/25 Javascript
干货分享:让你分分钟学会javascript闭包
2015/12/25 Javascript
input file上传 图片预览功能实例代码
2016/10/25 Javascript
node.js学习之事件模块Events的使用示例
2017/09/28 Javascript
vue+elementUI实现图片上传功能
2019/08/20 Javascript
js中script的上下放置区别,Dom的增删改创建操作实例分析
2019/12/16 Javascript
微信小程序实现比较功能的方法汇总(五种方法)
2020/03/07 Javascript
viewer.js实现图片预览功能
2020/06/24 Javascript
python中实现php的var_dump函数功能
2015/01/21 Python
Python批量转换文件编码格式
2015/05/17 Python
搞笑的程序猿:看看你是哪种Python程序员
2015/06/12 Python
windows下python安装小白入门教程
2018/09/18 Python
python实现的自动发送消息功能详解
2019/08/15 Python
Python函数的定义方式与函数参数问题实例分析
2019/12/26 Python
python-docx文件定位读取过程(尝试替换)
2020/02/13 Python
Python3+selenium实现cookie免密登录的示例代码
2020/03/18 Python
python可视化 matplotlib画图使用colorbar工具自定义颜色
2020/12/07 Python
客服主管岗位职责
2013/12/13 职场文书
学生自我鉴定模板
2013/12/30 职场文书
新闻发布会主持词
2014/03/28 职场文书
公司领导班子对照材料
2014/08/18 职场文书
民族团结演讲稿范文
2014/08/27 职场文书
中班上学期个人总结
2015/02/12 职场文书
2015年度对口支援工作总结
2015/07/22 职场文书
css height属性中的calc方法详解
2021/06/03 HTML / CSS
golang操作rocketmq的示例代码
2022/04/06 Golang
Golang ort 中的sortInts 方法
2022/04/24 Golang