| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- <script setup lang="ts">
- import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
- import {
- getSlideOffset,
- slideInit,
- slideReset,
- slideTouchEnd,
- slideTouchMove,
- slideTouchStart,
- } from '@/utils/slide'
- import { SlideType } from '@/utils/const_var'
- import { _css } from '@/utils/dom'
- const props = defineProps({
- index: { type: Number, default: 0 },
- name: { type: String, default: '' },
- autoplay: { type: Boolean, default: false },
- indicator: { type: Boolean, default: false },
- changeActiveIndexUseAnim: { type: Boolean, default: true },
- })
- const emit = defineEmits<{ 'update:index': [number] }>()
- let ob: MutationObserver | null = null
- const slideListEl = ref<HTMLElement | null>(null)
- const state = reactive({
- judgeValue: 20,
- type: SlideType.HORIZONTAL,
- name: props.name,
- localIndex: props.index,
- needCheck: true,
- next: false,
- isDown: false,
- start: { x: 0, y: 0, time: 0 },
- move: { x: 0, y: 0 },
- wrapper: { width: 0, height: 0, childrenLength: 0 },
- })
- watch(
- () => props.index,
- (newVal) => {
- if (state.localIndex !== newVal) {
- state.localIndex = newVal
- if (!slideListEl.value) return
- if (props.changeActiveIndexUseAnim) {
- _css(slideListEl.value, 'transition-duration', '300ms')
- }
- _css(
- slideListEl.value,
- 'transform',
- `translate3d(${getSlideOffset(state, slideListEl.value)}px, 0, 0)`,
- )
- }
- },
- )
- onMounted(() => {
- if (!slideListEl.value) return
- slideInit(slideListEl.value, state)
- if (props.autoplay) {
- setInterval(() => {
- if (state.localIndex === state.wrapper.childrenLength - 1) {
- emit('update:index', 0)
- } else {
- emit('update:index', state.localIndex + 1)
- }
- }, 3000)
- }
- ob = new MutationObserver(() => {
- if (slideListEl.value) state.wrapper.childrenLength = slideListEl.value.children.length
- })
- ob.observe(slideListEl.value, { childList: true })
- })
- onUnmounted(() => {
- ob?.disconnect()
- })
- function touchStart(e: PointerEvent) {
- if (slideListEl.value) slideTouchStart(e, slideListEl.value, state)
- }
- function touchMove(e: PointerEvent) {
- if (slideListEl.value) slideTouchMove(e, slideListEl.value, state)
- }
- function touchEnd(e: PointerEvent) {
- slideTouchEnd(e, state)
- if (slideListEl.value) slideReset(e, slideListEl.value, state, emit)
- }
- </script>
- <template>
- <div class="slide horizontal">
- <div
- v-if="indicator && state.wrapper.childrenLength"
- class="indicator-bullets"
- >
- <div
- v-for="item in state.wrapper.childrenLength"
- :key="item"
- class="bullet"
- :class="{ active: state.localIndex === item - 1 }"
- />
- </div>
- <div
- ref="slideListEl"
- class="slide-list"
- @pointerdown.prevent="touchStart"
- @pointermove.prevent="touchMove"
- @pointerup.prevent="touchEnd"
- >
- <slot />
- </div>
- </div>
- </template>
- <style scoped lang="less">
- .indicator-bullets {
- position: absolute;
- bottom: 10rem;
- z-index: 2;
- left: 50%;
- transform: translateX(-50%);
- display: flex;
- justify-content: center;
- gap: 7rem;
- .bullet {
- width: 5rem;
- height: 5rem;
- border-radius: 50%;
- background: var(--second-btn-color);
- &.active {
- background: white;
- }
- }
- }
- </style>
|