blob: 2f441579fe0cc9c5e0c3eefb8cb228966625c477 [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";
11
12 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 }
90 if(this.options.autoPlay > 500 && this.loop){
91 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;
107 setInterval(function(){
108 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);
114 }, self.options.autoPlay)
115 };
116 // 设置当前分页
117 auiSlide.prototype.setPaginationActive = function(index){
118 var self = this;
119 if(self.options.currentPage){
120 self.options.currentPage(index);
121 }
122 if(!this.container.querySelector(__SLIDE_PAGE_WRAP)){
123 return;
124 }
125 var pageList = this.container.querySelectorAll(__SLIDE_PAGE);
126 if(this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE)){
127 this.container.querySelector(__SLIDE_PAGE+__SLIDE_PAGE_ACTIVE).classList.remove(CLASS_SLIDE_PAGE_ACTIVE);
128 }
129 if(!this.continuous){
130 if(this.index == 3){
131 pageList[1].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
132 }else if(this.index==2){
133 pageList[0].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
134 }else{
135 pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
136 }
137 }else{
138 pageList[this.index].classList.add(CLASS_SLIDE_PAGE_ACTIVE);
139 }
140
141 };
142 // 创建分页器
143 auiSlide.prototype.createPagination = function(index){
144 var self = this;
145 var pageWrap = this.container.querySelector(__SLIDE_PAGE_WRAP);
146 if(!pageWrap){
147 return;
148 }
149 pageWrap.innerHTML = '';
150 var pageShowHtml = '';
151 switch (self.options.pageStyle) {
152 case "dot":// 原点
153 if (!this.continuous) {
154 for (var i = 0; i < 2; i++) {
155 pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>';
156 }
157 }else{
158 for (var i = 0; i < this.slideNodeListLength; i++) {
159 pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_DOT+'"></span>';
160 }
161 }
162 pageWrap.innerHTML = pageShowHtml;
163 self.setPaginationActive(0);
164 break;
165 case "line":// 线条
166 if (!this.continuous) {
167 for (var i = 0; i < 2; i++) {
168 pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:50%"></span>';
169 }
170 }else{
171 for (var i = 0; i < this.slideNodeListLength; i++) {
172 pageShowHtml += '<span class="'+CLASS_SLIDE_PAGE+' '+CLASS_SLIDE_PAGE_LINE+'" style="width:'+(100/this.slideNodeListLength)+'%"></span>';
173 }
174 }
175 pageWrap.innerHTML = pageShowHtml;
176 self.setPaginationActive(0);
177 break;
178 }
179 };
180 // 总页数
181 auiSlide.prototype.pageCount = function() {
182 var self = this;
183 return self.slideNodeList.length;
184 };
185 auiSlide.prototype.touchStart = function(event) {
186 touchStartTime = new Date() * 1;
187 firstTouchX = parseInt(event.changedTouches[0].pageX);
188 firstTouchY = parseInt(event.changedTouches[0].pageY);
189 isScrolling = undefined;
190 };
191 auiSlide.prototype.touchMove = function(event) {
192 var touchMoveObj = event.changedTouches[0],
193 touchX = parseInt(touchMoveObj.pageX);
194 touchXDelta = touchX - firstTouchX;
195 handleTranslateVal = touchXDelta/this.options.friction;
196 // 滑动位移
197 offsetX = parseInt(touchMoveObj.pageX) - firstTouchX;
198 offsetY = parseInt(touchMoveObj.pageY) - firstTouchY;
199 var direction = this.getDirection(offsetX,offsetY);
200 if ( typeof isScrolling == 'undefined') {
201 isScrolling = !!( isScrolling || Math.abs(offsetX) < Math.abs(offsetY) );
202 }
203 if(!isScrolling){
204 event.preventDefault();
205 if(!this.loop){ //不循环
206 if(!this.continuous && this.index==1 && direction=='left'){
207 return;
208 }
209 if(!this.continuous && this.index==0 && direction=='right'){
210 return;
211 }
212 if(this.index == this.slideNodeList.length-1){
213 if(handleTranslateVal <= 0){
214 return;
215 }
216 this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0);
217 }else if(this.index == 0){
218 if(handleTranslateVal >= 0){
219 return;
220 }
221 this.setTranslate(this.getCircle(this.index+1), this.slideWrapWidth, 0);
222 }
223 }
224
225 this.setTranslate(this.getCircle(this.index-1), handleTranslateVal - this.slideWrapWidth, 0);
226 this.setTranslate(this.index, handleTranslateVal , 0);
227 this.setTranslate(this.getCircle(this.index+1), handleTranslateVal + this.slideWrapWidth, 0);
228
229 }
230 };
231 auiSlide.prototype.touchEnd = function(event) {
232 var touchEndObj = event.changedTouches[0];
233 var touchEndX = parseInt(touchEndObj.pageX) - firstTouchX;
234 var touchEndY = parseInt(touchEndObj.pageY) - firstTouchY;
235 var touchEndxy = {
236 x: touchEndObj.pageX || 0,
237 y: touchEndObj.pageY || 0
238 };
239 var moveDirection = this.getDirection(touchEndX,touchEndY); //滑动方向
240 var boundary = this.slideWrapWidth/4;
241 var duration = (new Date() * 1) - touchStartTime;
242 var isValid = Number(duration) < 250 && Math.abs(offsetX) > 20 || Math.abs(offsetX) > boundary;
243 if (isScrolling) {
244 return;
245 }
246 if(isValid){
247 if(offsetX < 0){
248 if(!this.loop && this.index == this.slideNodeList.length-1){
249 return;
250 }
251
252 if(!this.loop && !this.continuous && this.index==1){
253 return;
254 }
255
256 if(offsetX < -boundary && moveDirection == 'left'){
257 // left
258 this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, 0);
259 this.slideTo(this.getCircle(this.index+2), this.slideWrapWidth, 0);
260 this.slideTo(this.index, -this.slideWrapWidth, this.speed);
261 this.slideTo(this.getCircle(this.index+1), 0, this.speed);
262 this.index = this.getCircle(this.index+1);
263 }else{
264 // this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
265 this.slideTo(this.index, 0, this.speed);
266 this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
267 }
268 }else if(offsetX > 0){
269 if(!this.loop && this.index == 0){
270 return;
271 }
272 if(!this.loop && !this.continuous && this.index==0){
273 return;
274 }
275 if(offsetX > boundary && moveDirection == 'right'){
276 // right
277 this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, 0);
278 this.slideTo(this.getCircle(this.index-2), -this.slideWrapWidth, 0);
279 this.slideTo(this.index, this.slideWrapWidth, this.speed);
280 this.slideTo(this.getCircle(this.index-1), 0, this.speed);
281 this.index = this.getCircle(this.index-1);
282 }else{
283 // this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
284 this.slideTo(this.index, 0, this.speed);
285 this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
286 }
287 }
288 }else{
289 if(offsetX){
290 this.slideTo(this.getCircle(this.index-1), -this.slideWrapWidth, this.speed);
291 this.slideTo(this.index, 0, this.speed);
292 this.slideTo(this.getCircle(this.index+1), this.slideWrapWidth, this.speed);
293 }
294
295 }
296 this.setPaginationActive(this.index);
297 };
298 auiSlide.prototype.setTranslate = function (index,dist,speed){
299 if(this.slideNodeList[index]){
300 this.slideNodeList[index].style.webkitTransitionDuration =
301 this.slideNodeList[index].style.transitionDuration = speed + 'ms';
302 this.slideNodeList[index].style.webkitTransform =
303 this.slideNodeList[index].style.transform = "translate3d("+dist+"px,0,0)";
304 }
305 };
306 auiSlide.prototype.slideTo = function (index, dist, speed) {
307 this.setTranslate(index, dist, speed);
308 // index = dist;
309 };
310 auiSlide.prototype.getCircle = function (index) {
311 return (this.slideNodeListLength + (index % this.slideNodeListLength)) % this.slideNodeListLength;
312 };
313 auiSlide.prototype.getDirection = function(x, y) {
314 if (x === y) { return '';}
315 if (Math.abs(x) >= Math.abs(y)) {
316 return x > 0 ? 'right' : 'left';
317 } else {
318 return y > 0 ? 'down' : 'up';
319 }
320 }
321 function extend (a, b) {
322 for (var key in b) {
323 if (b.hasOwnProperty(key)) {
324 a[key] = b[key];
325 }
326 }
327 return a;
328 }
329 function auiSlide (options) {
330 this._init(options);
331 }
332 window.auiSlide = auiSlide;
333})(window);