blob: f2b79b390e1cf6cab4535dc308ec1c1c6d72b23c [file] [log] [blame]
qiaoweif044a742019-07-10 16:04:20 +08001/**
2 * aui-slide.js 轮播组件
3 * @author 流浪男
4 * http://www.auicss.com
5 * @todo more things to abstract, e.g. Loading css etc.
6 * Licensed under the MIT license.
7 * http://www.opensource.org/licenses/mit-license.php
8 */
9(function(window) {
10 "use strict";
qiaoweibd656ad2020-06-11 15:12:03 +080011 var autoInderval;
qiaoweif044a742019-07-10 16:04:20 +080012 var translateVal,
13 firstTouchX,
14 firstTouchY,
15 touchXDelta,
16 handleTranslateVal;
17 var touchStartTime; //开始触摸事件
18 var offsetX,
19 offsetY,
20 isScrolling;
21 // CLASS 组装
22 var CLASS_SLIDER_NODE = "aui-slide-node",
23 CLASS_SLIDE_PAGE_WRAP = "aui-slide-page-wrap",
24 CLASS_SLIDE_PAGE = "aui-slide-page",
25 CLASS_SLIDE_PAGE_ACTIVE = "aui-slide-page-active",
26 CLASS_SLIDE_PAGE_DOT = "aui-slide-page-dot",
27 CLASS_SLIDE_PAGE_LINE = "aui-slide-page-line";
28
29 var __SLIDER_NODE = "."+CLASS_SLIDER_NODE,
30 __SLIDE_PAGE_WRAP = "."+CLASS_SLIDE_PAGE_WRAP,
31 __SLIDE_PAGE = "."+CLASS_SLIDE_PAGE,
32 __SLIDE_PAGE_ACTIVE = "."+CLASS_SLIDE_PAGE_ACTIVE;
33
34 auiSlide.prototype.options = {
35 container:'',
36 width:'auto',
37 height:'auto',
38 speed: 300, //滑动速速
39 autoPlay: 0, //自动播放
40 pageShow: true, //是否显示分页器
41 pageStyle: 'dot',
42 dotPosition: 'center',
43 friction:1, //阻力
44 loop:true,
45 currentPage:false,
46 PageCount:false
47 };
48 auiSlide.prototype._init = function(options) {
49 extend(this.options, options);
50 if(!this.options.container){
51 return;
52 }
53 this.index = 0; //索引值
54 this.continuous = true;//用于判断长度为2时的特殊处理
55 this.container = this.options.container;
56 // console.log(this.options.loop);
57 this.loop = this.options.loop;
58 this.speed = this.options.speed;
59 this.container.style.position = "relative";
60 this.container.style.width = this.options.width+"px";
61 this.container.style.height = this.options.height+"px";
62
63 var element = this.container.children[0];
64 this.slideWrap = element;
65 this.slideNodeList = this.slideWrap.querySelectorAll(__SLIDER_NODE);
66 if(!element || !this.slideNodeList){
67 return;
68 }
69 // this.options.pageCount(this.slideNodeList.length);
70 this.slideWrapWidth = this.slideWrap.offsetWidth;
71 this.slideNodeListLength = this.slideNodeList.length;
72
73 if (this.slideNodeListLength == 2) { //当长度为2时作特殊处理
74 element.appendChild(this.slideWrap.children[0].cloneNode(true));
75 element.appendChild(this.slideWrap.children[1].cloneNode(true));
76 this.slideWrap = element;
77 this.slideNodeList = this.slideWrap.querySelectorAll(__SLIDER_NODE);
78 this.slideNodeListLength = this.slideNodeList.length;
79 this.continuous = false;
80 }
81 for (var i = 0; i < this.slideNodeListLength; i++) {
82 this.slideNodeList[i] && (this.slideNodeList[i].style.webkitTransform = this.slideNodeList[i].style.transform = "translate3d("+(this.slideWrapWidth*i)+"px,0,0)");
83 }
84
85 if(this.slideNodeListLength > 1) {
86 if(this.options.pageShow){
87 this.createPagination(0);
88 this.setPageDotPosition();
89 }
qiaoweibd656ad2020-06-11 15:12:03 +080090 if(this.options.autoPlay > 500){
qiaoweif044a742019-07-10 16:04:20 +080091 this.autoPlay(0);
92 }
93 this.slideWrap.addEventListener('touchstart', this.touchStart.bind(this), false);
94 this.slideWrap.addEventListener('touchmove', this.touchMove.bind(this), false);
95 this.slideWrap.addEventListener('touchend', this.touchEnd.bind(this), false);
96 }
97 };
98 // 当分页器为圆点时位置设置
99 auiSlide.prototype.setPageDotPosition = function(){
100 var self = this;
101 var pageDotPosition = self.options.dotPosition;
102 this.container.querySelector(__SLIDE_PAGE_WRAP).style.textAlign = pageDotPosition;
103 };
104 // 自动播放
105 auiSlide.prototype.autoPlay = function (index) {
106 var self = this;
qiaoweibd656ad2020-06-11 15:12:03 +0800107 autoInderval = setInterval(function(){
qiaoweif044a742019-07-10 16:04:20 +0800108 self.slideTo(self.getCircle(self.index-1), -self.slideWrapWidth, 0);
109 self.slideTo(self.getCircle(self.index+2), self.slideWrapWidth, 0);
110 self.slideTo(self.index, -self.slideWrapWidth, self.options.speed);
111 self.slideTo(self.getCircle(self.index+1), 0, self.options.speed);
112 self.index = self.getCircle(self.index+1);
113 self.setPaginationActive(self.index);
qiaoweibd656ad2020-06-11 15:12:03 +0800114 if((self.index+1)==self.pageCount()){
115 if(!self.options.loop){
116 clearInterval(autoInderval);
117 }
118 }
qiaoweif044a742019-07-10 16:04:20 +0800119 }, self.options.autoPlay)
120 };
121 // 设置当前分页
122 auiSlide.prototype.setPaginationActive = function(index){
123 var self = this;
124 if(self.options.currentPage){
125 self.options.currentPage(index);
126 }
127 if(!this.container.querySelector(__SLIDE_PAGE_WRAP)){
128 return;
129 }
130 var pageList = this.container.querySelectorAll(__SLIDE_PAGE);
131 if(this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE)){
132 this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE).classList.remove(CLASS_SLIDE_PAGE_ACTIVE);
133 }
134 if(!this.continuous){
135 if(this.index == 3){
136 pageList[1].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
137 }else if(this.index==2){
138 pageList[0].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
139 }else{
140 pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
141 }
142 }else{
143 pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
144 }
145
146 };
147 // 创建分页器
148 auiSlide.prototype.createPagination = function(index){
149 var self = this;
150 var pageWrap = this.container.querySelector(__SLIDE_PAGE_WRAP);
151 if(!pageWrap){
152 return;
153 }
154 pageWrap.innerHTML = '';
155 var pageShowHtml = '';
156 switch (self.options.pageStyle) {
157 case "dot":// 原点
158 if (!this.continuous) {
159 for (var i = 0; i < 2; i++) {
160 pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>';
161 }
162 }else{
163 for (var i = 0; i < this.slideNodeListLength; i++) {
164 pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>';
165 }
166 }
167 pageWrap.innerHTML = pageShowHtml;
168 self.setPaginationActive(0);
169 break;
170 case "line":// 线条
171 if (!this.continuous) {
172 for (var i = 0; i < 2; i++) {
173 pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:50%"></span>';
174 }
175 }else{
176 for (var i = 0; i < this.slideNodeListLength; i++) {
177 pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:'+(100/this.slideNodeListLength)+'%"></span>';
178 }
179 }
180 pageWrap.innerHTML = pageShowHtml;
181 self.setPaginationActive(0);
182 break;
183 }
184 };
185 // 总页数
186 auiSlide.prototype.pageCount = function() {
187 var self = this;
188 return self.slideNodeList.length;
189 };
190 auiSlide.prototype.touchStart = function(event) {
191 touchStartTime = new Date() * 1;
192 firstTouchX = parseInt(event.changedTouches[0].pageX);
193 firstTouchY = parseInt(event.changedTouches[0].pageY);
194 isScrolling = undefined;
195 };
196 auiSlide.prototype.touchMove = function(event) {
197 var touchMoveObj = event.changedTouches[0],
198 touchX = parseInt(touchMoveObj.pageX);
199 touchXDelta = touchX - firstTouchX;
200 handleTranslateVal = touchXDelta/this.options.friction;
201 // 滑动位移
202 offsetX = parseInt(touchMoveObj.pageX) - firstTouchX;
203 offsetY = parseInt(touchMoveObj.pageY) - firstTouchY;
204 var direction = this.getDirection(offsetX,offsetY);
205 if ( typeof isScrolling == 'undefined') {
206 isScrolling = !!( isScrolling || Math.abs(offsetX) < Math.abs(offsetY) );
207 }
208 if(!isScrolling){
209 event.preventDefault();
210 if(!this.loop){ //不循环
211 if(!this.continuous && this.index==1 && direction=='left'){
212 return;
213 }
214 if(!this.continuous && this.index==0 && direction=='right'){
215 return;
216 }
217 if(this.index == this.slideNodeList.length-1){
218 if(handleTranslateVal <= 0){
219 return;
220 }
221 this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0);
222 }else if(this.index == 0){
223 if(handleTranslateVal >= 0){
224 return;
225 }
226 this.setTranslate(this.getCircle(this.index+1), this.slideWrapWidth, 0);
227 }
228 }
229
230 this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0);
231 this.setTranslate(this.index, handleTranslateVal , 0);
232 this.setTranslate(this.getCircle(this.index+1), handleTranslateVal + this.slideWrapWidth, 0);
233
234 }
235 };
236 auiSlide.prototype.touchEnd = function(event) {
237 var touchEndObj = event.changedTouches[0];
238 var touchEndX = parseInt(touchEndObj.pageX) - firstTouchX;
239 var touchEndY = parseInt(touchEndObj.pageY) - firstTouchY;
240 var touchEndxy = {
241 x: touchEndObj.pageX || 0,
242 y: touchEndObj.pageY || 0
243 };
244 var moveDirection = this.getDirection(touchEndX,touchEndY); //滑动方向
245 var boundary = this.slideWrapWidth/4;
246 var duration = (new Date() * 1) - touchStartTime;
247 var isValid = Number(duration) < 250 && Math.abs(offsetX) > 20 || Math.abs(offsetX) > boundary;
248 if (isScrolling) {
249 return;
250 }
251 if(isValid){
252 if(offsetX < 0){
253 if(!this.loop && this.index == this.slideNodeList.length-1){
254 return;
255 }
256
257 if(!this.loop && !this.continuous && this.index==1){
258 return;
259 }
260
261 if(offsetX < -boundary && moveDirection == 'left'){
262 // left
263 this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, 0);
264 this.slideTo(this.getCircle(this.index+2), this.slideWrapWidth, 0);
265 this.slideTo(this.index, -this.slideWrapWidth, this.speed);
266 this.slideTo(this.getCircle(this.index+1), 0, this.speed);
267 this.index = this.getCircle(this.index+1);
268 }else{
269 // this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
270 this.slideTo(this.index, 0, this.speed);
271 this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
272 }
273 }else if(offsetX > 0){
274 if(!this.loop && this.index == 0){
275 return;
276 }
277 if(!this.loop && !this.continuous && this.index==0){
278 return;
279 }
280 if(offsetX > boundary && moveDirection == 'right'){
281 // right
282 this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, 0);
283 this.slideTo(this.getCircle(this.index-2), -this.slideWrapWidth, 0);
284 this.slideTo(this.index, this.slideWrapWidth, this.speed);
285 this.slideTo(this.getCircle(this.index-1), 0, this.speed);
286 this.index = this.getCircle(this.index-1);
287 }else{
288 // this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
289 this.slideTo(this.index, 0, this.speed);
290 this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
291 }
292 }
293 }else{
294 if(offsetX){
295 this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
296 this.slideTo(this.index, 0, this.speed);
297 this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
298 }
299
300 }
301 this.setPaginationActive(this.index);
302 };
303 auiSlide.prototype.setTranslate = function (index,dist,speed){
304 if(this.slideNodeList[index]){
305 this.slideNodeList[index].style.webkitTransitionDuration =
306 this.slideNodeList[index].style.transitionDuration = speed + 'ms';
307 this.slideNodeList[index].style.webkitTransform =
308 this.slideNodeList[index].style.transform = "translate3d("+dist+"px,0,0)";
309 }
310 };
311 auiSlide.prototype.slideTo = function (index, dist, speed) {
312 this.setTranslate(index, dist, speed);
313 // index = dist;
314 };
315 auiSlide.prototype.getCircle = function (index) {
316 return (this.slideNodeListLength + (index % this.slideNodeListLength)) % this.slideNodeListLength;
317 };
318 auiSlide.prototype.getDirection = function(x, y) {
319 if (x === y) { return '';}
320 if (Math.abs(x) >= Math.abs(y)) {
321 return x > 0 ? 'right' : 'left';
322 } else {
323 return y > 0 ? 'down' : 'up';
324 }
325 }
326 function extend (a, b) {
327 for (var key in b) {
328 if (b.hasOwnProperty(key)) {
329 a[key] = b[key];
330 }
331 }
332 return a;
333 }
334 function auiSlide (options) {
335 this._init(options);
336 }
337 window.auiSlide = auiSlide;
338})(window);