獎品列表元件【仿swiper】
阿新 • • 發佈:2018-12-17
/** * 我們在各個活動工具中要用到swiper去做獎品列表的渲染,由於swiper.js和swiper.css檔案較大;所以仿照swiper封裝了此元件 * @param {Object} config * @param {String} containerId:選擇器 * @param {Number} slidesPerView:一屏要展示數 * @param {Number} spaceBetween:獎品間距 * @param {Boolean} scrollbarHide:是否顯示滾動條 */ import './index.scss'; class CSlide { init(config) { let { containerId, slidesPerView, spaceBetween = 20, scrollbarHide } = config; this.container = document.querySelector(containerId); this.wrapper = this.container.children[0]; this.store = { containerId, containerWidth: this.wrapper.offsetWidth, children: this.wrapper.children, slidesPerView, spaceBetween, calculateSlideX: 0, scrollbarHide }; this.state = { startX: 0, diffX: 0, touchStart: false, touchEnd: false, touchMove: false, translateX: 0, transitionDuring: 300, ifanimateEnd: false }; this.buildSwiper(); } bind() { let events = ['touchstart', 'touchmove', 'touchend']; this.addEvent(this.container, events[0], this.touchStart); this.addEvent(this.container, events[1], this.touchMove); this.addEvent(this.container, events[2], this.touchEnd); } //初始化內容 buildSwiper() { let { containerWidth, children, slidesPerView, spaceBetween } = this.store; let slideWidth = Math.round(containerWidth / slidesPerView); for (let i = 0; i < children.length; i++) { children[i].style.width = slideWidth + 'px'; children[i].style.marginRight = spaceBetween + 'px'; } //是否有滾動條 if (this.store.scrollbarHide) { $(this.store.containerId).append(` <div class="swiper-scrollbar"> <div class="swiper-scrollbar-drag"></div> </div>`); this.srollbarContainer = document.querySelector('.swiper-scrollbar-drag'); this.scrollbar = document.querySelector('.swiper-scrollbar'); this.store.scrollbarWidth = this.scrollbar.offsetWidth; this.store.scrollbarDragWidth = this.srollbarContainer.offsetWidth; setTimeout(() => { this.store.ableslideX = Number(this.scrollbar.offsetWidth - this.srollbarContainer.offsetWidth); }, 10); } this.bind(); } //監聽touchStart事件 touchStart(e, that) { if (that.state.touchStart) return; that.state.startX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX; that.state.touchEnd = that.state.touchMove = false; that.state.touchStart = true; that.state.diffX = 0; } //監聽touchMove事件 touchMove(e, that) { let { startX } = that.state; if (!that.state.touchStart) return; that.state.touchMove = true; let currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; if (!that.state.ifanimateEnd) { that.state.diffX = Math.round(currentX - startX); that.targetMaxmove(); if(that.store.scrollbarHide){ that.scrollbarMove(); } } } //監聽touchEnd事件 touchEnd(e, that) { let { touchStart, touchMove, touchEnd, } = that.state; if (!touchStart || !touchMove || touchEnd) return; that.state.touchEnd = true; that.state.touchStart = false; that.state.ifanimateEnd = false; that.ifdeadLine(); if(that.store.scrollbarHide){ that.scrollbarInit(); } setTimeout(() => { that.transitionDurationEndFn(); }, that.state.transitionDuring); } //返回滑動區域的最大值 calculateSlide() { let { children, spaceBetween, containerWidth } = this.store; let slide_max = 0, totalWidth = 0; for (let i = 0; i < children.length; i++) { totalWidth += children[0].offsetWidth + spaceBetween; } slide_max = containerWidth + spaceBetween - totalWidth; return slide_max; } //滑動的臨界值判斷 targetMaxmove() { let { diffX } = this.state; let currentSlide = this.state.diffX + this.getTranslate(this.wrapper).x; let rightLine = this.calculateSlide(); if (diffX > 0 && currentSlide > this.store.containerWidth / 2) { this.state.ifanimateEnd = true; this.state.translateX = this.store.containerWidth / 2; } else if (diffX < 0 && currentSlide <= rightLine - this.store.containerWidth / 2) { this.state.ifanimateEnd = true; this.state.translateX = rightLine - this.store.containerWidth / 2; } else { this.state.translateX = currentSlide; } this.recover(this.wrapper, Number(this.state.translateX), 0, 0); } //結束時臨界值處理 ifdeadLine() { let { diffX, translateX } = this.state; let rightLine = this.calculateSlide(); if (diffX > 0) { this.recover(this.wrapper, 0, 0, 0); } if (diffX < 0 && translateX <= rightLine) { this.recover(this.wrapper, rightLine, 0, 0); } } //滾動條滑動處理 scrollbarMove() { let { diffX } = this.state; let { ableslideX } = this.store; let rightLine = this.calculateSlide(); let radio = Math.abs(diffX) / Math.abs(rightLine); let scrollX = diffX > 0 ? -radio * ableslideX : radio * ableslideX; scrollX += this.getTranslate(this.srollbarContainer).x; this.recover(this.srollbarContainer, scrollX, 0, 0); } //結束滾動條處理 scrollbarInit() { let { ableslideX } = this.store; let { diffX } = this.state; let scrollX = this.getTranslate(this.srollbarContainer).x; if (diffX > 0) { this.recover(this.srollbarContainer, 0, 0, 0); } if (diffX < 0 && scrollX > ableslideX) { this.recover(this.srollbarContainer, ableslideX, 0, 0); } } recover(container, x, y, z) { this.transitionDuration(container, this.state.transitionDuring); this.translate(container, x, y, z); } translate(ele, x, y, z) { this.transform(ele, 'translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)'); } transform(ele, transform) { let elStyle = ele.style; elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform; } transitionDuration(ele, time) { let elStyle = ele.style; elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = time + 'ms'; } transitionDurationEndFn() { this.transitionDuration(this.wrapper, 0); } getTranslate(el) { let curStyle = window.getComputedStyle(el); let curTransform = curStyle.transform || curStyle.webkitTransform; let x, y; x = y = 0; curTransform = curTransform.split(', '); if (curTransform.length === 6) { x = parseInt(curTransform[4], 10); y = parseInt(curTransform[5], 10); } return { x, y }; } addEvent(target, type, fn) { $(document).on(type, target, event => { if (typeof fn !== 'function') return; fn(event, this); }).bind(this); } };