first commit
This commit is contained in:
111
components/Ml/SliderPoint/MlSliderPoint.vue
Normal file
111
components/Ml/SliderPoint/MlSliderPoint.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div v-show="showSwiper" class="relative" :class="rootClasses">
|
||||
<swiper
|
||||
loop-add-blank-slides
|
||||
:class="sliderClasses"
|
||||
:direction="direction"
|
||||
:space-between="50"
|
||||
:breakpoints="{
|
||||
2000: { slidesPerView: 1, spaceBetween: 40 },
|
||||
}"
|
||||
@swiper="onSwiper"
|
||||
@slide-change="onSlideChange"
|
||||
>
|
||||
<swiper-slide
|
||||
v-for="slide in 4"
|
||||
:key="slide"
|
||||
class="h-full hover:cursor-pointer"
|
||||
>
|
||||
<slot />
|
||||
</swiper-slide>
|
||||
</swiper>
|
||||
<div
|
||||
class="flex justify-between items-center h-10 cursor-pointer"
|
||||
:class="counterClasses"
|
||||
>
|
||||
<div
|
||||
v-for="(slide, index) in 4"
|
||||
:key="index"
|
||||
:class="[
|
||||
'bg-BgDark dark:bg-BgLight h-[3px] transition-all duration-500',
|
||||
index === currentSlideNumber
|
||||
? 'py-2 w-[16px] rounded-3xl'
|
||||
: 'w-[25px] rounded-sm md:w-[24px]',
|
||||
]"
|
||||
@click="goToSlide(index), stopAutoSlide()"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, defineProps, withDefaults, onMounted } from "vue";
|
||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||
import type { Swiper as swiper } from "swiper/types";
|
||||
import "swiper/css";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import type { PTAttribs } from "./types";
|
||||
|
||||
const showSwiper = ref(false);
|
||||
const currentSlideNumber = ref(0);
|
||||
let swiperInstance: swiper | null = null;
|
||||
let intervalId: number | null = null;
|
||||
|
||||
const onSwiper = (swiper: swiper) => {
|
||||
swiperInstance = swiper;
|
||||
showSwiper.value = true;
|
||||
};
|
||||
|
||||
const onSlideChange = (swiper: swiper) => {
|
||||
currentSlideNumber.value = swiper.realIndex;
|
||||
};
|
||||
|
||||
function startAutoSlide() {
|
||||
intervalId = setInterval(() => {
|
||||
const nextSlide = (currentSlideNumber.value + 1) % 4;
|
||||
goToSlide(nextSlide);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function goToSlide(index: number) {
|
||||
swiperInstance?.slideTo(index);
|
||||
currentSlideNumber.value = index;
|
||||
}
|
||||
|
||||
function stopAutoSlide() {
|
||||
if (intervalId !== null) {
|
||||
clearInterval(intervalId);
|
||||
intervalId = null;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
startAutoSlide();
|
||||
});
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
direction: "horizontal" | "vertical";
|
||||
pt?: PTAttribs;
|
||||
}>(),
|
||||
{
|
||||
direction: "horizontal",
|
||||
}
|
||||
);
|
||||
|
||||
const classes = ref({
|
||||
root: { class: `` },
|
||||
slider: { class: `` },
|
||||
counter: { class: `mx-auto px-6 container` },
|
||||
} as PTAttribs);
|
||||
|
||||
const rootClasses = computed(() =>
|
||||
twMerge(classes.value.root?.class, props.pt?.root?.class)
|
||||
);
|
||||
const sliderClasses = computed(() =>
|
||||
twMerge(classes.value.slider?.class, props.pt?.slider?.class)
|
||||
);
|
||||
const counterClasses = computed(() =>
|
||||
twMerge(classes.value.counter?.class, props.pt?.counter?.class)
|
||||
);
|
||||
</script>
|
21
components/Ml/SliderPoint/types.ts
Normal file
21
components/Ml/SliderPoint/types.ts
Normal file
@ -0,0 +1,21 @@
|
||||
export type SliderProps = {
|
||||
rounded?: boolean;
|
||||
pt?: PTAttribs;
|
||||
};
|
||||
|
||||
export type PTAttribs = {
|
||||
root?: {
|
||||
class: string;
|
||||
};
|
||||
slider?: {
|
||||
class: string;
|
||||
};
|
||||
counter?: {
|
||||
class: string;
|
||||
};
|
||||
direction?: {
|
||||
direction: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type spinerPlace = 'suffix' | 'prefix';
|
Reference in New Issue
Block a user