基于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 相关文章推荐
JXTree对象,读取外部xml文件数据,生成树的函数
Apr 02 Javascript
JQuery一种取同级值的方式(比如你在GridView中)
Mar 15 Javascript
javascript控制Div层透明属性由浅变深由深变浅逐渐显示
Nov 12 Javascript
jquery导航制件jquery鼠标经过变色效果示例
Dec 05 Javascript
JS密码生成与强度检测完整实例(附demo源码下载)
Apr 06 Javascript
Ionic如何实现下拉刷新与上拉加载功能
Jun 03 Javascript
jQuery 3.0 的 setter和getter 模式详解
Jul 11 Javascript
Bootstrap模态框案例解析
Mar 05 Javascript
使用jQuery实现购物车结算功能
Aug 15 jQuery
VSCode中如何利用d.ts文件进行js智能提示
Apr 13 Javascript
Vue中在新窗口打开页面及Vue-router的使用
Jun 13 Javascript
Electron-vue脚手架改造vue项目的方法
Oct 22 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
教你IIS6的PHP最佳配置方法
2006/09/05 PHP
使用PHP反射机制来构造&quot;CREATE TABLE&quot;的sql语句
2019/03/21 PHP
JavaScript Event学习第七章 事件属性
2010/02/07 Javascript
jquery统计复选框选中示例
2013/11/05 Javascript
屏蔽相应键盘按钮操作
2014/03/10 Javascript
JavaScript框架(iframe)操作总结
2014/04/16 Javascript
js实现点击后将文字或图片复制到剪贴板的方法
2014/08/04 Javascript
JQuery中serialize() 序列化
2015/03/13 Javascript
jQuery的基本概念与高级编程
2015/05/14 Javascript
js实现TAB切换对应不同颜色的代码
2015/08/31 Javascript
浏览器环境下JavaScript脚本加载与执行探析之defer与async特性
2016/01/14 Javascript
Bootstrap中表单控件状态(验证状态)
2016/08/04 Javascript
javascript判断firebug是否开启的方法
2016/11/23 Javascript
Node学习记录之cluster模块
2017/05/31 Javascript
jQuery 实现图片的依次加载图片功能
2017/07/06 jQuery
详解vue-cli 快速搭建单页应用之遇到的问题及解决办法
2018/03/01 Javascript
BootStrap中的模态框(modal,弹出层)功能示例代码
2018/11/02 Javascript
node express使用HTML模板的方法示例
2019/08/22 Javascript
微信小程序商品详情页底部弹出框
2019/11/22 Javascript
[07:26]2015国际邀请赛第二日TOP10集锦
2015/08/06 DOTA
Python操作json数据的一个简单例子
2014/04/17 Python
一些Python中的二维数组的操作方法
2015/05/02 Python
Python的collections模块中的OrderedDict有序字典
2016/07/07 Python
Python文件操作,open读写文件,追加文本内容实例
2016/12/14 Python
讲解Python3中NumPy数组寻找特定元素下标的两种方法
2019/08/04 Python
详解python中的模块及包导入
2019/08/30 Python
python 消费 kafka 数据教程
2019/12/21 Python
Python制作一个仿QQ办公版的图形登录界面
2020/09/22 Python
CSS3 Pie工具推荐--让IE6-8支持一些优秀的CSS3特性
2014/09/02 HTML / CSS
迪卡侬比利时官网:Decathlon比利时
2019/12/28 全球购物
学生自我鉴定范文
2013/10/04 职场文书
学习型党组织建设经验材料
2014/05/26 职场文书
2014年仓库管理员工作总结
2014/11/18 职场文书
vue首次渲染全过程
2021/04/21 Vue.js
python实现会员管理系统
2022/03/18 Python
Win11 21h2可以升级22h2吗?看看你的电脑符不符合要求
2022/07/07 数码科技