基于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 相关文章推荐
学习js所必须要知道的一些
Mar 07 Javascript
十个优秀的Ajax/Javascript实例网站收集
Mar 31 Javascript
浅谈JavaScript中的作用域和闭包问题
Jul 07 Javascript
浅析如何利用JavaScript进行语音识别
Oct 27 Javascript
使用jQuery ajaxupload插件实现无刷新上传文件
Apr 23 jQuery
JS中使用textPath实现线条上的文字
Dec 25 Javascript
使用async-validator编写Form组件的方法
Jan 10 Javascript
vue使用Element组件时v-for循环里的表单项验证方法
Jun 28 Javascript
vue发送ajax请求详解
Oct 09 Javascript
Javascript Dom元素获取和添加详解
Sep 24 Javascript
JavaScript实现手风琴效果
Feb 18 Javascript
详解JS WebSocket断开原因和心跳机制
May 07 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
无法在发生错误时创建会话,请检查 PHP 或网站服务器日志,并正确配置 PHP 安装最快的解决办法
2010/08/01 PHP
php入门学习知识点二 PHP简单的分页过程与原理
2011/07/14 PHP
php中通过正则表达式下载内容中的远程图片的函数代码
2012/01/10 PHP
9段PHP实用功能的代码推荐
2014/10/14 PHP
PHP实现的常规正则验证helper公共类完整实例
2017/04/27 PHP
jquery 图片Silhouette Fadeins渐显效果
2010/02/07 Javascript
Jquery中val()表单取值赋值的实例代码
2013/08/15 Javascript
JQuery中使用Ajax赋值给全局变量异常的解决方法
2014/01/10 Javascript
js 实现浏览历史记录示例
2014/04/20 Javascript
js写出遮罩层登陆框和对联广告并自动跟随滚动条滚动
2014/04/29 Javascript
js实现星星打分效果的方法
2020/07/05 Javascript
延时加载JavaScript代码提高速度
2015/12/27 Javascript
微信小程序实现带刻度尺滑块功能
2017/03/29 Javascript
JavaScript数据结构中串的表示与应用实例
2017/04/12 Javascript
Vue2.0基于vue-cli+webpack父子组件通信(实例讲解)
2017/09/14 Javascript
基于BootStrap的文本编辑器组件Summernote
2017/10/27 Javascript
微信小程序实现滚动加载更多的代码
2019/12/06 Javascript
javascript 数组精简技巧小结
2020/02/26 Javascript
Python 用户登录验证的小例子
2013/03/06 Python
Python 记录日志的灵活性和可配置性介绍
2018/02/27 Python
对python中的float除法和整除法的实例详解
2019/07/20 Python
pycharm显示远程图片的实现
2019/11/04 Python
10个Python面试常问的问题(小结)
2019/11/20 Python
python 识别登录验证码图片功能的实现代码(完整代码)
2020/07/03 Python
python如何实现图片压缩
2020/09/11 Python
利用CSS3的checked伪类实现OL的隐藏显示的方法
2010/12/18 HTML / CSS
斯洛伐克香水和化妆品购物网站:Parfemy-Elnino.sk
2020/01/28 全球购物
法国亚马逊官方网站:Amazon.fr
2020/12/19 全球购物
node中使用shell脚本的方法步骤
2021/03/23 Javascript
英语专业学生个人求职信
2014/01/28 职场文书
学习雷锋倡议书
2014/04/15 职场文书
安全生产承诺书范文
2014/05/22 职场文书
新农村建设汇报材料
2014/08/15 职场文书
离职证明标准格式
2014/09/15 职场文书
简历自我评价模板
2015/03/11 职场文书
Python使用scapy模块发包收包
2021/05/07 Python