@opensig/opendesign
Version:
204 lines (203 loc) • 6.51 kB
JavaScript
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
};