Currently, only the effects of scroll and none have been added. scroll is the sliding effect and can support sliding in the x and y directions; none has no effect, just shows and hides. Later, other effects need to be added and expanded. The writing is a bit rough. Haha, leave a note here to prevent it from being lost.
Demo Address: http://demo.jb51.net/js/2012/sinaapp/
/**
* Big Mac Carousel
*/
$.fn.loopSlider = function(option) {
var setting = {
//Default display order
initIndex: 1 ,
// Style added to the title node
className: "current",
// Carousel direction, the default is x-axis carousel
direct: "x",
// Previous button
prevBtn: "",
// Next button
nextBtn: "",
// Disabled style of page up and down buttons
btnDisable: "disable ",
//Button press style
btnTouchClass: "",
// Automatic carousel
auto: false,
// Automatic carousel time interval
timeFlag: 4000,
// Carousel effect time
scrollTime: 350,
// Carousel effect
effect: "scroll",
// Whether to hide when there is only one carousel element Sliding button
hideBtn: true,
// Whether to cycle the carousel
cycle: true,
// Container path of the carousel content area
contentContainer: "#imgScroll",
//Nodes of the carousel content area
contentChildTag: "li",
// Container path of the title carousel area
titleContainer: "#titleScroll",
// Title carousel area Node
titleChildTag: "li",
// Array of carousel content area
cont: [],
// Array of carousel title area
tabs: [] ,
// Current carousel number
current: 0,
// Timer
ptr: "",
// Carousel callback function, called each time the carousel is called, the parameters are The serial number of the current carousel
callback: function() {
return true;
}
}
if (option) {
$.extend(setting, option);
}
//Initialize the function of the current calling type
setting.currentMethod = function() {
return true;
}
var boss = $(this);
// If it is not the first element, rotate it first
if (setting.initIndex != 1) {
setting.current = setting.initIndex - 1;
}
// Get the list of rotating nodes
var childList = boss.find(setting.contentContainer " " setting.contentChildTag);
// Get the carousel title node list
var titleList = boss.find(setting.titleContainer " " setting.titleChildTag) ;
// Save each carousel node in the content area
setting.cont = childList;
// Save the carousel node of the title
setting.tabs = titleList;
// If not For content that needs to be rotated, directly return
if (setting.cont.length == 0) {
return;
}
// Set the index attribute
childList for the content area and title area .each(function(index) {
$(this).attr("index", index);
titleList.eq(index).attr("index", index);
});
// Up and down arrows
var nextBtn = boss.find(setting.nextBtn);
var prevBtn = boss.find(setting.prevBtn);
// Length
var counts = childList .length;
// The parent node of the carousel container
var childParent = childList.parent();
var titleParent = titleList.parent();
if (childList.length < setting. initIndex) {
setting.current = 0;
}
//Initialization
doInit();
if (childList.length <= 1) {
return;
}
/**
* Handle switching without effect
*/
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);
// record Currently displayed node
setting.current = i;
// Call the callback function
setting.callback(setting.current);
},
init: function() {
setting.currentMethod = doScrollNone;
bindEvent();
// Automatic carousel
if (setting.auto) {
processAuto();
}
// During initialization Also call the callback function
setting.callback(setting.current);
}
};
var doScrollXY = {
c_width: 0,
c_height: 0,
init : function() {
//The width of the carousel element
this.c_width = childList.width();
//The height of the carousel element
this.c_height = childList.height() ;
// x-axis direction carousel
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;
// Binding event
bindEvent();
// The callback function is also called during initialization
setting.callback(setting.current);
//Auto carousel
if (setting.auto) {
processAuto();
}
},
process : function(i, needFast) {
setting.current = i;
//alert(i)
if (setting.direct == "x") {
//Execute effect animation
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);
}
}
/**
* Bind carousel event
*/
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;
}
// Finger sliding event
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;
// The purpose here is to prevent the browser's default event when sliding the image left or right. However, if it is sliding up and down, it is usually sliding the scroll bar. You cannot directly prevent the browser's default event, otherwise it will cause the user to slide up and down. When the page stops, the setting here is to slide at least 10 more pixels in the x-axis direction than in the Y-axis direction, which can effectively avoid the above situation from happening
if (Math.abs(x) - Math.abs (y) > 10) {
// Prevent the default event
moveEvent.preventDefault();
childParent.css("left", parseFloat(currentPosition) x);
moveDirect = x > 0 ? "sub": "add";
} else {
return;
}
} else {
//Scroll in Y-axis direction
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;
}
//The finger leaves the screen
function handleTouchEnd() {
//According to the finger The direction of movement, determine the next node number to be displayed
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;
}
}
// Call the corresponding processing Function
setting.currentMethod.process(setting.current, fast);
childParent[0].ontouchend = null;
childParent[0].ontouchmove = null;
}
}
}
/**
* Automatic carousel
*/
function processAuto() {
if (setting.ptr) {
clearInterval(setting.ptr);
setting.ptr = null ;
}
//Set the carousel timer
setting.ptr = setInterval(function() {
if (setting.current == counts) {
setting.current = 1;
} else if (setting.current == counts - 1) {
// Carousel to the last one
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) ;
}
// Returns a function. You can call the return function to specify the serial number of the picture that needs to be rotated next time. It is generally used when you click on a small picture and then need to view the larger picture, then You only need to bind a carousel event to the big picture. When you click on a small picture, you only need to call this function and pass in the corresponding serial number.
return function(index) {
if (index < 0) {
index = 0;
} else if (index >= counts) {
index = counts - 1;
}
setting.currentMethod.process(index);
}
}