| /** |
| * aui-slide.js 轮播组件 |
| * @author 流浪男 |
| * http://www.auicss.com |
| * @todo more things to abstract, e.g. Loading css etc. |
| * Licensed under the MIT license. |
| * http://www.opensource.org/licenses/mit-license.php |
| */ |
| (function(window) { |
| "use strict"; |
| |
| var translateVal, |
| firstTouchX, |
| firstTouchY, |
| touchXDelta, |
| handleTranslateVal; |
| var touchStartTime; //开始触摸事件 |
| var offsetX, |
| offsetY, |
| isScrolling; |
| // CLASS 组装 |
| var CLASS_SLIDER_NODE = "aui-slide-node", |
| CLASS_SLIDE_PAGE_WRAP = "aui-slide-page-wrap", |
| CLASS_SLIDE_PAGE = "aui-slide-page", |
| CLASS_SLIDE_PAGE_ACTIVE = "aui-slide-page-active", |
| CLASS_SLIDE_PAGE_DOT = "aui-slide-page-dot", |
| CLASS_SLIDE_PAGE_LINE = "aui-slide-page-line"; |
| |
| var __SLIDER_NODE = "."+CLASS_SLIDER_NODE, |
| __SLIDE_PAGE_WRAP = "."+CLASS_SLIDE_PAGE_WRAP, |
| __SLIDE_PAGE = "."+CLASS_SLIDE_PAGE, |
| __SLIDE_PAGE_ACTIVE = "."+CLASS_SLIDE_PAGE_ACTIVE; |
| |
| auiSlide.prototype.options = { |
| container:'', |
| width:'auto', |
| height:'auto', |
| speed: 300, //滑动速速 |
| autoPlay: 0, //自动播放 |
| pageShow: true, //是否显示分页器 |
| pageStyle: 'dot', |
| dotPosition: 'center', |
| friction:1, //阻力 |
| loop:true, |
| currentPage:false, |
| PageCount:false |
| }; |
| auiSlide.prototype._init = function(options) { |
| extend(this.options, options); |
| if(!this.options.container){ |
| return; |
| } |
| this.index = 0; //索引值 |
| this.continuous = true;//用于判断长度为2时的特殊处理 |
| this.container = this.options.container; |
| // console.log(this.options.loop); |
| this.loop = this.options.loop; |
| this.speed = this.options.speed; |
| this.container.style.position = "relative"; |
| this.container.style.width = this.options.width+"px"; |
| this.container.style.height = this.options.height+"px"; |
| |
| var element = this.container.children[0]; |
| this.slideWrap = element; |
| this.slideNodeList = this.slideWrap.querySelectorAll(__SLIDER_NODE); |
| if(!element || !this.slideNodeList){ |
| return; |
| } |
| // this.options.pageCount(this.slideNodeList.length); |
| this.slideWrapWidth = this.slideWrap.offsetWidth; |
| this.slideNodeListLength = this.slideNodeList.length; |
| |
| if (this.slideNodeListLength == 2) { //当长度为2时作特殊处理 |
| element.appendChild(this.slideWrap.children[0].cloneNode(true)); |
| element.appendChild(this.slideWrap.children[1].cloneNode(true)); |
| this.slideWrap = element; |
| this.slideNodeList = this.slideWrap.querySelectorAll(__SLIDER_NODE); |
| this.slideNodeListLength = this.slideNodeList.length; |
| this.continuous = false; |
| } |
| for (var i = 0; i < this.slideNodeListLength; i++) { |
| this.slideNodeList[i] && (this.slideNodeList[i].style.webkitTransform = this.slideNodeList[i].style.transform = "translate3d("+(this.slideWrapWidth*i)+"px,0,0)"); |
| } |
| |
| if(this.slideNodeListLength > 1) { |
| if(this.options.pageShow){ |
| this.createPagination(0); |
| this.setPageDotPosition(); |
| } |
| if(this.options.autoPlay > 500 && this.loop){ |
| this.autoPlay(0); |
| } |
| this.slideWrap.addEventListener('touchstart', this.touchStart.bind(this), false); |
| this.slideWrap.addEventListener('touchmove', this.touchMove.bind(this), false); |
| this.slideWrap.addEventListener('touchend', this.touchEnd.bind(this), false); |
| } |
| }; |
| // 当分页器为圆点时位置设置 |
| auiSlide.prototype.setPageDotPosition = function(){ |
| var self = this; |
| var pageDotPosition = self.options.dotPosition; |
| this.container.querySelector(__SLIDE_PAGE_WRAP).style.textAlign = pageDotPosition; |
| }; |
| // 自动播放 |
| auiSlide.prototype.autoPlay = function (index) { |
| var self = this; |
| setInterval(function(){ |
| self.slideTo(self.getCircle(self.index-1), -self.slideWrapWidth, 0); |
| self.slideTo(self.getCircle(self.index+2), self.slideWrapWidth, 0); |
| self.slideTo(self.index, -self.slideWrapWidth, self.options.speed); |
| self.slideTo(self.getCircle(self.index+1), 0, self.options.speed); |
| self.index = self.getCircle(self.index+1); |
| self.setPaginationActive(self.index); |
| }, self.options.autoPlay) |
| }; |
| // 设置当前分页 |
| auiSlide.prototype.setPaginationActive = function(index){ |
| var self = this; |
| if(self.options.currentPage){ |
| self.options.currentPage(index); |
| } |
| if(!this.container.querySelector(__SLIDE_PAGE_WRAP)){ |
| return; |
| } |
| var pageList = this.container.querySelectorAll(__SLIDE_PAGE); |
| if(this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE)){ |
| this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE).classList.remove(CLASS_SLIDE_PAGE_ACTIVE); |
| } |
| if(!this.continuous){ |
| if(this.index == 3){ |
| pageList[1].classList.add(CLASS_SLIDE_PAGE_ACTIVE); |
| }else if(this.index==2){ |
| pageList[0].classList.add(CLASS_SLIDE_PAGE_ACTIVE); |
| }else{ |
| pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE); |
| } |
| }else{ |
| pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE); |
| } |
| |
| }; |
| // 创建分页器 |
| auiSlide.prototype.createPagination = function(index){ |
| var self = this; |
| var pageWrap = this.container.querySelector(__SLIDE_PAGE_WRAP); |
| if(!pageWrap){ |
| return; |
| } |
| pageWrap.innerHTML = ''; |
| var pageShowHtml = ''; |
| switch (self.options.pageStyle) { |
| case "dot":// 原点 |
| if (!this.continuous) { |
| for (var i = 0; i < 2; i++) { |
| pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>'; |
| } |
| }else{ |
| for (var i = 0; i < this.slideNodeListLength; i++) { |
| pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>'; |
| } |
| } |
| pageWrap.innerHTML = pageShowHtml; |
| self.setPaginationActive(0); |
| break; |
| case "line":// 线条 |
| if (!this.continuous) { |
| for (var i = 0; i < 2; i++) { |
| pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:50%"></span>'; |
| } |
| }else{ |
| for (var i = 0; i < this.slideNodeListLength; i++) { |
| pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:'+(100/this.slideNodeListLength)+'%"></span>'; |
| } |
| } |
| pageWrap.innerHTML = pageShowHtml; |
| self.setPaginationActive(0); |
| break; |
| } |
| }; |
| // 总页数 |
| auiSlide.prototype.pageCount = function() { |
| var self = this; |
| return self.slideNodeList.length; |
| }; |
| auiSlide.prototype.touchStart = function(event) { |
| touchStartTime = new Date() * 1; |
| firstTouchX = parseInt(event.changedTouches[0].pageX); |
| firstTouchY = parseInt(event.changedTouches[0].pageY); |
| isScrolling = undefined; |
| }; |
| auiSlide.prototype.touchMove = function(event) { |
| var touchMoveObj = event.changedTouches[0], |
| touchX = parseInt(touchMoveObj.pageX); |
| touchXDelta = touchX - firstTouchX; |
| handleTranslateVal = touchXDelta/this.options.friction; |
| // 滑动位移 |
| offsetX = parseInt(touchMoveObj.pageX) - firstTouchX; |
| offsetY = parseInt(touchMoveObj.pageY) - firstTouchY; |
| var direction = this.getDirection(offsetX,offsetY); |
| if ( typeof isScrolling == 'undefined') { |
| isScrolling = !!( isScrolling || Math.abs(offsetX) < Math.abs(offsetY) ); |
| } |
| if(!isScrolling){ |
| event.preventDefault(); |
| if(!this.loop){ //不循环 |
| if(!this.continuous && this.index==1 && direction=='left'){ |
| return; |
| } |
| if(!this.continuous && this.index==0 && direction=='right'){ |
| return; |
| } |
| if(this.index == this.slideNodeList.length-1){ |
| if(handleTranslateVal <= 0){ |
| return; |
| } |
| this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0); |
| }else if(this.index == 0){ |
| if(handleTranslateVal >= 0){ |
| return; |
| } |
| this.setTranslate(this.getCircle(this.index+1), this.slideWrapWidth, 0); |
| } |
| } |
| |
| this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0); |
| this.setTranslate(this.index, handleTranslateVal , 0); |
| this.setTranslate(this.getCircle(this.index+1), handleTranslateVal + this.slideWrapWidth, 0); |
| |
| } |
| }; |
| auiSlide.prototype.touchEnd = function(event) { |
| var touchEndObj = event.changedTouches[0]; |
| var touchEndX = parseInt(touchEndObj.pageX) - firstTouchX; |
| var touchEndY = parseInt(touchEndObj.pageY) - firstTouchY; |
| var touchEndxy = { |
| x: touchEndObj.pageX || 0, |
| y: touchEndObj.pageY || 0 |
| }; |
| var moveDirection = this.getDirection(touchEndX,touchEndY); //滑动方向 |
| var boundary = this.slideWrapWidth/4; |
| var duration = (new Date() * 1) - touchStartTime; |
| var isValid = Number(duration) < 250 && Math.abs(offsetX) > 20 || Math.abs(offsetX) > boundary; |
| if (isScrolling) { |
| return; |
| } |
| if(isValid){ |
| if(offsetX < 0){ |
| if(!this.loop && this.index == this.slideNodeList.length-1){ |
| return; |
| } |
| |
| if(!this.loop && !this.continuous && this.index==1){ |
| return; |
| } |
| |
| if(offsetX < -boundary && moveDirection == 'left'){ |
| // left |
| this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, 0); |
| this.slideTo(this.getCircle(this.index+2), this.slideWrapWidth, 0); |
| this.slideTo(this.index, -this.slideWrapWidth, this.speed); |
| this.slideTo(this.getCircle(this.index+1), 0, this.speed); |
| this.index = this.getCircle(this.index+1); |
| }else{ |
| // this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed); |
| this.slideTo(this.index, 0, this.speed); |
| this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed); |
| } |
| }else if(offsetX > 0){ |
| if(!this.loop && this.index == 0){ |
| return; |
| } |
| if(!this.loop && !this.continuous && this.index==0){ |
| return; |
| } |
| if(offsetX > boundary && moveDirection == 'right'){ |
| // right |
| this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, 0); |
| this.slideTo(this.getCircle(this.index-2), -this.slideWrapWidth, 0); |
| this.slideTo(this.index, this.slideWrapWidth, this.speed); |
| this.slideTo(this.getCircle(this.index-1), 0, this.speed); |
| this.index = this.getCircle(this.index-1); |
| }else{ |
| // this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed); |
| this.slideTo(this.index, 0, this.speed); |
| this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed); |
| } |
| } |
| }else{ |
| if(offsetX){ |
| this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed); |
| this.slideTo(this.index, 0, this.speed); |
| this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed); |
| } |
| |
| } |
| this.setPaginationActive(this.index); |
| }; |
| auiSlide.prototype.setTranslate = function (index,dist,speed){ |
| if(this.slideNodeList[index]){ |
| this.slideNodeList[index].style.webkitTransitionDuration = |
| this.slideNodeList[index].style.transitionDuration = speed + 'ms'; |
| this.slideNodeList[index].style.webkitTransform = |
| this.slideNodeList[index].style.transform = "translate3d("+dist+"px,0,0)"; |
| } |
| }; |
| auiSlide.prototype.slideTo = function (index, dist, speed) { |
| this.setTranslate(index, dist, speed); |
| // index = dist; |
| }; |
| auiSlide.prototype.getCircle = function (index) { |
| return (this.slideNodeListLength + (index % this.slideNodeListLength)) % this.slideNodeListLength; |
| }; |
| auiSlide.prototype.getDirection = function(x, y) { |
| if (x === y) { return '';} |
| if (Math.abs(x) >= Math.abs(y)) { |
| return x > 0 ? 'right' : 'left'; |
| } else { |
| return y > 0 ? 'down' : 'up'; |
| } |
| } |
| function extend (a, b) { |
| for (var key in b) { |
| if (b.hasOwnProperty(key)) { |
| a[key] = b[key]; |
| } |
| } |
| return a; |
| } |
| function auiSlide (options) { |
| this._init(options); |
| } |
| window.auiSlide = auiSlide; |
| })(window); |