UNPKG

@opensig/opendesign

Version:

204 lines (203 loc) 6.51 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { normalizeClass, nextTick } from "vue"; import { isFunction } from "../../_utils/is.mjs"; import Effect from "./effect.mjs"; import { useResizeObserver } from "../../hooks/use-resize-observer.mjs"; import { debounceRAF } from "../../_utils/helper.mjs"; import "../../hooks/use-theme.mjs"; import "../../_utils/global.mjs"; import "@vueuse/core"; class Gallery extends Effect { constructor(slideElList, slideContainer, activeIndex, options) { super(slideElList, slideContainer, options); __publicField(this, "container"); __publicField(this, "slideList"); __publicField(this, "alignType"); __publicField(this, "moveValue"); __publicField(this, "isChanging"); __publicField(this, "isSliding"); // 是否在切换 __publicField(this, "oldMoveValue"); __publicField(this, "destroyObserver"); __publicField(this, "resolveArr"); const { alignType = "center" } = options || {}; this.total = slideElList.length; this.resolveArr = []; slideContainer.addEventListener("transitionend", () => { slideContainer.style.willChange = ""; slideContainer.classList.remove("is-animating"); this.isChanging = false; if (this.resolveArr.length > 0) { this.resolveArr.forEach((fn) => fn(null)); this.resolveArr = []; } }); this.alignType = alignType; this.moveValue = 0; this.isChanging = false; this.isSliding = false; this.oldMoveValue = 0; this.slideList = []; this.container = { el: slideContainer, width: 0 }; const or = useResizeObserver(); const listener = debounceRAF(() => { this.update(slideElList, slideContainer); this.active(activeIndex, false, true); }); or.observe(slideContainer, listener); this.destroyObserver = () => { or.unobserve(slideContainer, listener); }; } update(slideElList, slideContainer) { let s = 0; this.slideList = slideElList.map((el, idx) => { const w = el.clientWidth; const l = s; el.style.left = `${l}px`; s += w; return { index: idx, el, width: el.clientWidth, left: l }; }); this.container = { el: slideContainer, width: slideContainer.clientWidth }; } handleTouchStart() { this.oldMoveValue = this.moveValue; this.isSliding = true; } handleTouchMove(pos, e) { if (!this.isSliding) { return; } const { dx, dy } = pos; if (Math.abs(dx) > Math.abs(dy)) { this.isSliding = true; e.stopPropagation(); e.preventDefault(); e.stopImmediatePropagation(); this.transformX(this.oldMoveValue + dx, false); } else { this.isSliding = false; } } handleTouchEnd(pos) { this.isSliding = false; const { width: sw } = this.slideList[this.currentIndex]; const step = Math.abs(pos.dx) / sw > 0.2 ? 1 : 0; const toIdx = this.currentIndex + (pos.dx < 0 ? step : -1 * step); return toIdx; } active(toIndex, animate = true, force = false) { if (this.total === 0 || this.isChanging || !force && this.currentIndex === toIndex) { return Promise.resolve(null); } if (this.currentIndex !== toIndex && isFunction(this.onBeforeChange) && this.onBeforeChange(toIndex, this.currentIndex) === false) { Promise.resolve(null); } this.isChanging = animate; const toSlide = this.slideList[toIndex]; const fromSlide = this.slideList[this.currentIndex]; if (!toSlide) { return Promise.resolve(null); } toSlide.el.classList.add( "o-carousel-toggle-current" /* CURRENT */ ); fromSlide == null ? void 0 : fromSlide.el.classList.remove("o-carousel-toggle-current"); if (this.activeClass) { const classes = normalizeClass(this.activeClass).split(/\s+/).filter(Boolean); toSlide.el.classList.add(...classes); fromSlide == null ? void 0 : fromSlide.el.classList.remove(...classes); } if (!toSlide) { return Promise.resolve(null); } const { width: cw } = this.container; const { width: sw, left: sl } = toSlide; if (this.alignType === "center") { return this.transformX((cw - sw) / 2 - sl, animate).then(() => { if (isFunction(this.onChanged) && this.currentIndex !== toIndex) { this.onChanged(toIndex, this.currentIndex); } this.currentIndex = toIndex; nextTick().then(() => { this.loopRange(); }); return toIndex; }); } return Promise.resolve(toIndex); } loopRange() { const cidx = this.currentIndex; const half = (this.total - 1) / 2; const orderSlideList = []; const tm = []; for (let i = cidx; i <= cidx + Math.ceil(half); i++) { if (i < this.total) { orderSlideList.push(this.slideList[i]); tm.push(i); } else { orderSlideList.push(this.slideList[i - this.total]); tm.push(i - this.total); } } for (let i = cidx - 1; i >= cidx - Math.floor(half); i--) { if (i >= 0) { orderSlideList.unshift(this.slideList[i]); tm.unshift(i); } else { orderSlideList.unshift(this.slideList[this.total + i]); tm.unshift(this.total + i); } } let s = 0; const { left: oldLeft } = this.slideList[cidx]; orderSlideList.forEach((item) => { const { el, width } = item; el.style.left = `${s}px`; item.left = s; s += width; }); const { left: newLeft } = this.slideList[cidx]; const d = newLeft - oldLeft; this.transformX(this.moveValue - d, false); } transformX(value, animate = true) { return new Promise((resolve) => { this.moveValue = value; this.isChanging = false; const { el } = this.container; if (animate === true) { el.classList.add("is-animating"); } el.style.transform = `translate3d(${value}px,0,0)`; if (animate) { this.resolveArr.push(resolve); } else { resolve(null); } }); } destroyed() { if (isFunction(this.destroyObserver)) { this.destroyObserver(); } } } export { Gallery as default };