cczg-lottery-activity/uni_modules/zebra-swiper/components/z-swiper/z-swiper.vue

732 lines
22 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view :id="'swiper'+_uid"
:class="['swiper',contentClass,containerClasses,options.direction === 'vertical'?'swiper-vertical':'']"
:style="[customStyle]">
<!-- #ifndef MP-WEIXIN || MP-QQ -->
<view :class="['swiper-wrapper']" :style="[wrapperStyle]" @click="onClickWrapper" @touchstart="onTouchStart"
@touchmove="onTouchMove" @touchend="onTouchEnd" @touchcancel="onTouchEnd">
<!-- #endif -->
<!-- #ifdef MP-WEIXIN || MP-QQ -->
<view :class="['swiper-wrapper']" :style="[wrapperStyle]" @click="onClickWrapper"
@touchstart="zSwiperWxs.onTouchStartWxs" @touchmove="zSwiperWxs.onTouchMoveWxs"
@touchend="zSwiperWxs.onTouchEndWxs" @touchcancel="zSwiperWxs.onTouchEndWxs"
:swiperTransform="wxsTransform" :change:swiperTransform="zSwiperWxs.wxsTransformObserver">
<!-- #endif -->
<slot></slot>
<!-- 在loop模式下为group填充空白slide -->
<template v-if="loopBlankShow">
<z-swiper-item v-for="(item,index) in loopBlankNumber" :key="index">
</z-swiper-item>
</template>
<template v-if="cubeShadowShowWrapper">
<view class="swiper-cube-shadow" :style="[cubeShadowStyle]"></view>
</template>
</view>
<template v-if="cubeShadowShowRoot">
<view class="swiper-cube-shadow" :style="[cubeShadowStyle]"></view>
</template>
<slot name="indicator"></slot>
<template v-if="showIndicators">
<view :class="['swiper-pagination',paginationClass]" :style="[paginationStyle]">
<template v-if="paginationType == 'bullets'">
<view v-for="(item,index) in paginationContent" :key="index"
:class="[item.classContent.join(' ')]" :style="[item.styleContent]"
@click="paginationItemClick(index)">
</view>
</template>
<template v-if="paginationType == 'fraction'">
<text :class="paginationContent.currentClass">{{paginationContent.text}}</text>/<text
:class="paginationContent.totalClass">{{paginationContent.total}}</text>
</template>
<template v-if="paginationType == 'progressbar'">
<text :class="paginationContent.progressbarFillClass"
:style="[paginationContent.styleContent]"></text>
</template>
</view>
</template>
<template v-if="(showPrevButton||showPrevButtonSlot)">
<view :class="['swiper-button-prev',prevClass]" @click="prevClick">
<view v-if="!showPrevButtonSlot" class="zebra-icon zebra-icon-circle_chevron_left"></view>
<slot v-else name="pre-button"></slot>
</view>
</template>
<template v-if="(showNextButton||showNextButtonSlot)">
<view :class="['swiper-button-next',nextClass]" @click="nextClick">
<view v-if="!showNextButtonSlot" class="zebra-icon zebra-icon-circle_chevron_right"></view>
<slot v-else name="next-button"></slot>
</view>
</template>
<template v-if="scrollbarShow">
<view :class="['swiper-scrollbar',scrollbarClass]" :style="[scrollbarStyle]"
@click.stop="onClickScrollbar" @touchstart.stop="onTouchStartScrollbar"
@touchmove.stop.prevent="onTouchMoveScrollbar" @touchend.stop="onTouchEndScrollbar">
<view class="swiper-scrollbar-drag" :style="[scrollbarItemStyle]">
</view>
</view>
</template>
</view>
</template>
<!-- #ifdef MP-WEIXIN || MP-QQ -->
<script src="../../wxs/z-swiper-wxs.wxs" module="zSwiperWxs" lang="wxs"></script>
<!-- #endif -->
<script>
import {
getAllRect,
getRect
} from '../../libs/utils/utils.js';
// vue2
import {
getParams
} from '../../libs/vue2/get-params.js';
import {
initSwiper,
mountSwiper
} from '../../libs/vue2/init-swiper.js';
import {
needsScrollbar,
needsNavigation,
needsPagination,
uniqueClasses,
extend,
} from '../../libs/vue2/utils.js';
import {
renderLoop,
calcLoopedSlides
} from '../../libs/vue2/loop.js';
import {
getChangedParams
} from '../../libs/vue2/get-changed-params.js';
import {
updateSwiper
} from '../../libs/vue2/update-swiper.js';
import {
renderVirtual,
updateOnVirtualData
} from '../../libs/vue2/virtual.js';
//mixin
import {
ParentMixin
} from '../../libs/mixins/relation.js';
export default {
name: "z-swipe",
// #ifdef MP-WEIXIN
options: {
virtualHost: true
},
// #endif
mixins: [
ParentMixin('zSwipe')
],
// #ifdef VUE3
emits: ['update:modelValue', 'touch-start', 'touch-move', 'touch-end', 'transitionend', 'slideClick',
'_beforeBreakpoint',
'_containerClasses',
'_slideClass',
'_slideClasses', '_swiper',
'activeIndexChange', 'afterInit', 'autoplay', 'autoplayStart', 'autoplayStop', 'autoplayPause',
'autoplayResume', 'beforeDestroy', 'beforeInit', 'beforeLoopFix', 'beforeResize', 'beforeSlideChangeStart',
'beforeTransitionStart', 'breakpoint', 'changeDirection', 'click', 'disable', 'doubleTap', 'doubleClick',
'destroy', 'enable', 'fromEdge', 'hashChange', 'hashSet', 'imagesReady', 'init', 'keyPress',
'lazyImageLoad', 'lazyImageReady', 'lock', 'loopFix', 'momentumBounce', 'navigationHide', 'navigationShow',
'observerUpdate', 'orientationchange', 'paginationHide', 'paginationRender', 'paginationShow',
'paginationUpdate', 'progress', 'reachBeginning', 'reachEnd', 'realIndexChange', 'resize', 'scroll',
'scrollbarDragEnd', 'scrollbarDragMove', 'scrollbarDragStart', 'setTransition', 'setTranslate',
'slideChange', 'slideChangeTransitionEnd', 'slideChangeTransitionStart', 'slideNextTransitionEnd',
'slideNextTransitionStart', 'slidePrevTransitionEnd', 'slidePrevTransitionStart',
'slideResetTransitionStart', 'slideResetTransitionEnd', 'sliderMove', 'sliderFirstMove',
'slidesLengthChange', 'slidesGridLengthChange', 'snapGridLengthChange', 'snapIndexChange', 'swiper', 'tap',
'toEdge', 'touchEnd', 'touchMove', 'touchMoveOpposite', 'touchStart', 'transitionEnd', 'transitionStart',
'unlock', 'update', 'zoomChange', 'beforeMount', 'nextClick', 'prevClick', 'touchStartScrollbar',
'touchMoveScrollbar', 'touchEndScrollbar', 'beforeUpdate', 'paginationItemClick'
],
// #endif
props: {
customStyle: {
type: Object,
default: () => {
return {};
}
},
options: {
type: Object,
default: () => {
return {}
}
},
// #ifdef VUE2
value: {
type: Array,
default: () => {
return []
}
},
// #endif
// #ifdef VUE3
modelValue: {
type: Array,
default: () => {
return []
}
}
// #endif
},
data() {
return {
wxsTransform: "",
wrapperStyle: {},
contentClass: '',
nextElClass: [],
prevElClass: [],
paginationElClass: [],
paginationItemElClass: [],
loopBlankShow: false,
loopBlankNumber: 0,
cubeShadowShowWrapper: false,
cubeShadowShowRoot: false,
cubeShadowStyle: {},
eventsListeners: {},
showPrevButton: false,
showPrevButtonSlot: false,
showNextButton: false,
showNextButtonSlot: false,
showIndicators: false,
paginationContent: [],
paginationType: '',
paginationStyle: {},
scrollbarElClass: [],
scrollbarStyle: {},
scrollbarItemStyle: {},
rectInfo: null,
// vue2
containerClasses: 'swiper',
virtualData: null,
firstLoad: true,
originalDataList: [],
loopUpdateData: false
};
},
computed: {
// #ifdef VUE3
value() {
return this.modelValue
},
// #endif
// #ifdef VUE3
_uid() {
return this._.uid
},
// #endif
nextClass() {
return this.nextElClass.join(" ");
},
prevClass() {
return this.prevElClass.join(" ");
},
paginationClass() {
return this.paginationElClass.join(" ");
},
paginationItemClass() {
return this.paginationItemElClass.join(" ");
},
scrollbarClass() {
return this.scrollbarElClass.join(" ");
},
scrollbarShow() {
return needsScrollbar(this.options)
}
},
created() {
const {
params: swiperParams,
passedParams
} = getParams(this.options);
this.swiperElRef = 'swiper';
this.swiperParams = swiperParams;
this.oldPassedParamsRef = passedParams;
let slidesRef = this.slidesRef;
swiperParams.onAny = (event, ...args) => {
// #ifdef MP
// 字节小程序此处报错因此无法使用v-on监听事件
// #ifndef MP-TOUTIAO
this.$emit(event, {}, ...args.filter((item, index) => {
return index > 0
}));
// #endif
// #endif
// #ifndef MP
this.$emit(event, ...args);
// #endif
};
Object.assign(swiperParams.on, {
_containerClasses(swiper, classes) {
this.containerClasses = classes;
},
});
this.$watch(() => {
return {
value: this.value,
options: this.options
}
}, (val) => {
// virtual模式处理
if (this.swiperParams && this.swiperParams.virtual) {
if (!this.virtualData && val.options.virtual.slides.length) {
this.swiperParams.virtual.slides = val.options.virtual.slides;
const extendWith = {
cache: false,
slides: val.options.virtual.slides,
renderExternal: data => {
this.virtualData = data;
// #ifdef VUE2
this.$emit("input", data.slides);
// #endif
// #ifdef VUE3
this.$emit("update:modelValue", data.slides);
// #endif
},
renderExternalUpdate: false
};
extend(this.swiperParams.virtual, extendWith);
this.loadSwiper();
}
}
// loop模式处理
if (this.swiperParams && this.swiperParams.loop) {
if (this.originalDataList.length && (this.originalDataList.toString() == val.value
.toString())) {
this.loopUpdateData = true;
// 百度小程序watch晚于子组件加载
// #ifdef MP-BAIDU
if (this.firstLoad) {
this.loadSwiper();
}
// #endif
} else {
this.loopUpdateData = false;
let slides = renderLoop(this, this.swiperParams, this.value);
if (this.swiperParams.loop && !this.loopUpdateData && slides.data.toString() !=
val.value.toString()) {
this.loopUpdateData = true;
// #ifdef VUE2
this.$emit("input", slides.data)
// #endif
// #ifdef VUE3
this.$emit("update:modelValue", slides.data)
// #endif
return
}
}
}
if (this.swiper && !this.firstLoad) {
if (this.virtualData && val.options.virtual.type == "cut") {
const style = this.swiper.isHorizontal() ? {
[this.swiper.rtlTranslate ? 'right' :
'left'
]: `${this.virtualData.offset}px`
} : {
top: `${this.virtualData.offset}px`
};
this.children
.map(slide => {
slide.css(style)
});
}
this.updateSwiper(val.value, val.options, this.children);
}
}, {
deep: true,
immediate: true
})
this.$watch(() => {
return this.$data
}, (val) => {
if (this.swiper && this.swiper.native) {
Object.assign(this.swiper.native, {
val
});
}
}, {
deep: true
})
this.$watch(() => {
return this.virtualData
}, (val) => {
if (this.swiper && this.virtualData) {
updateOnVirtualData(this.swiper);
}
}, {
deep: true
})
uni.$on("childrenReady" + this._uid, async (children) => {
children.dataSwiperSlideIndex = children.index;
if (this.children.length == this.value.length) {
Promise.all(this.children.map((item) => {
return item.getSize();
})).then((res) => {
if (this.swiperParams && this.swiperParams.loop) {
if (this.originalDataList.length && (this.originalDataList
.toString() == this.value
.toString())) {
if (this.firstLoad) {
this.loadSwiper();
}
} else {
return
}
} else {
if (this.firstLoad) {
this.loadSwiper();
}
}
this.updateSwiper(this.value, this.options, this.children);
})
}
})
},
// #ifdef VUE2
beforeDestroy() {
if (this.swiper && !this.swiper.destroyed) {
this.swiper.destroy(true, false);
}
},
// #endif
// #ifdef VUE3
beforeUnmount() {
if (this.swiper && !this.swiper.destroyed) {
this.swiper.destroy(true, false);
}
},
// #endif
methods: {
loadSwiper() {
let swiperParams = this.swiperParams;
this.slidesRef = this.children;
this.oldSlidesRef = this.slidesRef;
let swiperRef = initSwiper(swiperParams, {
...this.$data,
...this.$props,
swiperElId: 'swiper' + this._uid,
emit: this.emit.bind(this),
updateData: this.updateData.bind(this),
getRect: this.getRect.bind(this),
getRectScrollbar: this.getRectScrollbar.bind(this),
willChange: this.willChange.bind(this),
transform: this.transform.bind(this),
transition: this.transition.bind(this),
scrollbarTransform: this.scrollbarTransform.bind(this),
scrollbarTransition: this.scrollbarTransition.bind(this),
scrollbarItemTransform: this.scrollbarItemTransform.bind(this),
scrollbarItemTransition: this.scrollbarItemTransition.bind(this),
addClass: this.addClass.bind(this),
removeClass: this.removeClass.bind(this),
addPaginationClass: this.addPaginationClass.bind(this),
removePaginationClass: this.removePaginationClass.bind(this),
addScrollbarClass: this.addScrollbarClass.bind(this),
removeScrollbarClass: this.removeScrollbarClass.bind(this),
setCss: this.setCss.bind(this),
css: this.setCss.bind(this),
paginationCss: this.setPaginationCss.bind(this),
scrollbarCss: this.scrollbarCss.bind(this),
scrollbarItemCss: this.scrollbarItemCss.bind(this),
addNextElClass: this.addNextElClass.bind(this),
addPrevElClass: this.addPrevElClass.bind(this),
removeNextElClass: this.removeNextElClass.bind(this),
removePrevElClass: this.removePrevElClass.bind(this),
cubeShadowCss: this.cubeShadowCss.bind(this),
cubeShadowTransform: this.cubeShadowTransform.bind(this),
cubeShadowTransition: this.cubeShadowTransition.bind(this),
});
this.swiper = swiperRef;
swiperRef.loopCreate = () => {};
swiperRef.loopDestroy = () => {};
if (swiperParams.loop) {
swiperRef.loopedSlides = calcLoopedSlides(this.slidesRef, swiperParams);
}
if (!this.swiper) return;
mountSwiper({
el: this.swiperElRef,
nextEl: this.nextElRef,
prevEl: this.prevElRef,
paginationEl: this.paginationElRef,
scrollbarEl: this.scrollbarElRef,
swiper: this.swiper,
},
this.swiperParams,
);
this.$emit('swiper');
this.firstLoad = false;
},
updateSwiper(value, options, children) {
this.swiper.slides = children;
this.slidesRef = children;
let initializedRef = this.initializedRef;
let swiperRef = this.swiper;
let slidesRef = this.slidesRef;
let oldPassedParamsRef = this.oldPassedParamsRef;
let oldSlidesRef = this.oldSlidesRef;
let breakpointChanged = this.breakpointChanged;
let nextElRef = this.nextElRef;
let prevElRef = this.prevElRef;
let paginationElRef = this.paginationElRef;
let scrollbarElRef = this.scrollbarElRef;
// set initialized flag
if (!initializedRef && swiperRef) {
swiperRef.emitSlidesClasses();
initializedRef = true;
}
// watch for params change
const {
passedParams: newPassedParams
} = getParams(options);
const changedParams = getChangedParams(
newPassedParams,
oldPassedParamsRef,
slidesRef,
oldSlidesRef,
);
this.oldPassedParamsRef = newPassedParams;
this.oldSlidesRef = slidesRef;
if (
(changedParams.length || breakpointChanged) &&
swiperRef &&
!swiperRef.destroyed
) {
updateSwiper({
swiper: swiperRef,
slides: slidesRef,
passedParams: newPassedParams,
changedParams,
nextEl: nextElRef,
prevEl: prevElRef,
scrollbarEl: scrollbarElRef,
paginationEl: paginationElRef,
});
}
breakpointChanged = false;
},
emit(event, data) {
this.$emit(event, ...data)
},
async getRect() {
let rectInfo = await getRect(this, '.swiper');
this.rectInfo = rectInfo;
return rectInfo;
},
async getRectScrollbar() {
let rectInfo = await getRect(this, '.swiper-scrollbar');
return rectInfo;
},
updateData(value) {
Object.keys(value).forEach((item) => {
this.$set(this, item, value[item])
})
},
willChange(value) {
this.$set(this.wrapperStyle, 'will-change', value)
},
transform(value) {
// #ifndef MP-WEIXIN || MP-QQ
this.$set(this.wrapperStyle, 'transform', value)
// #endif
// #ifdef MP-WEIXIN || MP-QQ
this.wxsTransform = value;
// #endif
},
transition(value) {
// #ifdef MP-BAIDU
this.$set(this.wrapperStyle, 'transitionDuration', `${value}ms`)
// #endif
// #ifndef MP-BAIDU
this.$set(this.wrapperStyle, 'transition-duration', `${value}ms`)
// #endif
},
setCss(value) {
Object.keys(value).forEach((item) => {
this.$set(this.wrapperStyle, item, value[item])
})
},
scrollbarTransform(value) {
this.$set(this.scrollbarStyle, 'transform', value)
},
scrollbarTransition(value) {
this.$set(this.scrollbarStyle, 'transitionDuration', `${value}ms`)
},
scrollbarItemTransform(value) {
this.$set(this.scrollbarItemStyle, 'transform', value)
},
scrollbarItemTransition(value) {
this.$set(this.scrollbarItemStyle, 'transitionDuration', `${value}ms`)
},
addClass(value) {
// #ifdef MP-ALIPAY || MP-TOUTIAO
this.contentClass = Array.from(new Set([...this.contentClass.split(" "), ...value.split(" ")])).join(" ");
// #endif
// #ifndef MP-ALIPAY || MP-TOUTIAO
this.contentClass = Array.from(new Set([...this.contentClass, ...value.split(" ")]));
// #endif
},
removeClass(value) {
// #ifdef MP-ALIPAY || MP-TOUTIAO
this.contentClass = this.contentClass.split(" ").filter(item => !value.split(" ").includes(item)).join(
" ");
// #endif
// #ifndef MP-ALIPAY || MP-TOUTIAO
this.contentClass = this.contentClass.filter(item => !value.split(" ").includes(item));
// #endif
},
addPaginationClass(value) {
this.paginationElClass = Array.from(new Set([...this.paginationElClass, ...value.split(" ")]));
},
removePaginationClass(value) {
this.paginationElClass = this.paginationElClass.filter(item => !value.split(" ").includes(item));
},
addScrollbarClass(value) {
this.scrollbarElClass = Array.from(new Set([...this.scrollbarElClass, ...value.split(" ")]));
},
removeScrollbarClass(value) {
this.scrollbarElClass = this.scrollbarElClass.filter(item => !value.split(" ").includes(item));
},
setPaginationCss(value) {
Object.keys(value).forEach((item) => {
this.$set(this.paginationStyle, item, value[item])
})
},
scrollbarCss(value) {
Object.keys(value).forEach((item) => {
this.$set(this.scrollbarStyle, item, value[item])
})
},
scrollbarItemCss(value) {
Object.keys(value).forEach((item) => {
this.$set(this.scrollbarItemStyle, item, value[item])
})
},
addNextElClass(value) {
this.nextElClass = Array.from(new Set([...this.nextElClass, ...value.split(" ")]));
},
addPrevElClass(value) {
this.prevElClass = Array.from(new Set([...this.prevElClass, ...value.split(" ")]));
},
removeNextElClass(value) {
this.nextElClass = this.nextElClass.filter(item => !value.split(" ").includes(item));
},
removePrevElClass(value) {
this.prevElClass = this.prevElClass.filter(item => !value.split(" ").includes(item));
},
setSwiperOn(event, callback) {
if (!this.eventsListeners[event]) this.eventsListeners[event] = {};
this.eventsListeners[event] = callback;
},
paginationItemClick(index) {
this.swiper.emit("paginationItemClick", index)
},
prevClick() {
this.swiper.emit("prevClick");
},
nextClick() {
this.swiper.emit("nextClick");
},
onTouchStart(event) {
this.swiper.onTouchStart(event);
},
onTouchStartSwiperWxs(event) {
this.swiper.onTouchStart(event);
},
onTouchMove(event) {
this.swiper.onTouchMove(event);
},
onTouchMoveSwiperWxs(event) {
this.swiper.onTouchMove(event);
},
onTouchEnd(event) {
this.swiper.onTouchEnd(event);
},
onTouchEndSwiperWxs(event) {
this.swiper.onTouchEnd(event);
},
onClickWrapper(event) {
this.$emit("click", event);
},
onClickScrollbar(event) {
this.$emit("scrollbarClick", event);
},
onTouchStartScrollbar(event) {
this.swiper.emit('touchStartScrollbar', event);
},
onTouchMoveScrollbar(event) {
this.swiper.emit('touchMoveScrollbar', event);
},
onTouchEndScrollbar(event) {
this.swiper.emit('touchEndScrollbar', event);
},
cubeShadowCss(value) {
Object.keys(value).forEach((item) => {
this.$set(this.cubeShadowStyle, item, value[item])
})
},
cubeShadowTransform(value) {
this.$set(this.cubeShadowStyle, 'transform', value)
},
cubeShadowTransition(value) {
this.$set(this.cubeShadowStyle, 'transitionDuration', `${value}ms`)
},
}
}
</script>
<style scoped lang="scss">
@import '../../libs/core.scss';
@import "../../static/css/iconfont.css";
.swiper {
&__prev--button {
position: absolute;
left: 30rpx;
top: 50%;
display: flex;
color: #1989fa;
font-size: 44rpx;
z-index: 10;
}
&__prev--button--disable {
position: absolute;
left: 30rpx;
top: 50%;
display: flex;
color: #1989fa;
font-size: 44rpx;
opacity: .35;
z-index: 10;
}
&__next--button {
position: absolute;
right: 30rpx;
top: 50%;
display: flex;
color: #1989fa;
font-size: 44rpx;
z-index: 10;
}
&__next--button--disable {
position: absolute;
right: 30rpx;
top: 50%;
display: flex;
color: #1989fa;
font-size: 44rpx;
opacity: .35;
z-index: 10;
}
}
</style>