基于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函数ajax
Aug 20 Javascript
Mootools 1.2教程(2) DOM选择器
Sep 14 Javascript
js通过iframe加载外部网页的实现代码
Apr 05 Javascript
简单实现的JQuery文本框水印插件
Jun 14 Javascript
使用bootstrap-paginator.js 分页来进行ajax 异步分页请求示例
Mar 09 Javascript
javascript实现日期三级联动下拉框选择菜单
Dec 03 Javascript
js读取本地文件的实例
Dec 22 Javascript
Node.js利用console输出日志文件的方法示例
Apr 27 Javascript
js中Array对象的常用遍历方法详解
Jan 17 Javascript
微信小程序iBeacon测距及稳定程序的实现解析
Jul 31 Javascript
解决三元运算符 报错“SyntaxError: can''t assign to conditional expression”
Feb 12 Javascript
如何用JavaScript检测当前浏览器是无头浏览器
Apr 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
基于Zend的Config机制的应用分析
2013/05/02 PHP
PHP入门之常量简介和系统常量
2014/05/12 PHP
php字符串过滤与替换小结
2015/01/26 PHP
微信开发之获取JSAPI TICKET
2017/07/07 PHP
PHP实现一个限制实例化次数的类示例
2019/09/16 PHP
JavaScript 事件查询综合
2009/07/13 Javascript
将string解析为json的几种方式小结
2010/11/11 Javascript
js判断FCKeditor内容是否为空的两种形式
2013/05/14 Javascript
5分钟理解JavaScript中this用法分享
2013/11/09 Javascript
javascript修改表格背景色实例代码分享
2013/12/10 Javascript
解释&amp;&amp;和||在javascript中的另类用法
2014/07/28 Javascript
深入理解JavaScript中的对象
2015/06/04 Javascript
javascript插件开发的一些感想和心得
2016/02/28 Javascript
JS读写CSS样式的方法汇总
2016/08/16 Javascript
ES6新特性一: let和const命令详解
2017/04/20 Javascript
jquery.uploadifive插件怎么解决上传限制图片或文件大小问题
2017/05/08 jQuery
使用Webpack提高Vue.js应用的方式汇总(四种)
2017/07/10 Javascript
基于JavaScript实现弹幕特效
2020/08/27 Javascript
原生js实现移动端触摸轮播的示例代码
2017/12/22 Javascript
JS复杂判断的更优雅写法代码详解
2018/11/07 Javascript
Vue自定义指令上报Google Analytics事件统计的方法
2019/02/25 Javascript
微信小程序实现首页弹出广告
2020/12/03 Javascript
python实现文件快照加密保护的方法
2015/06/30 Python
zookeeper python接口实例详解
2018/01/18 Python
python自动发送邮件脚本
2018/06/20 Python
Python装饰器限制函数运行时间超时则退出执行
2019/04/09 Python
Python各种扩展名区别点整理
2020/02/27 Python
Tensorflow之MNIST CNN实现并保存、加载模型
2020/06/17 Python
EGO Shoes美国/加拿大:英国时髦鞋类品牌
2018/08/04 全球购物
实习单位接收函模板
2014/01/10 职场文书
员工培训邀请函
2014/01/11 职场文书
创业计划书如何编写
2014/02/06 职场文书
电气工程自动化求职信
2014/03/14 职场文书
文艺演出策划方案
2014/06/07 职场文书
一篇文章带你复习java知识点
2021/06/28 Java/Android
剖析后OpLog订阅MongoDB的数据变更就没那么难了
2022/02/24 MongoDB