You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
2.5 KiB
117 lines
2.5 KiB
3 months ago
|
<template>
|
||
|
<div class="embla">
|
||
|
<div class="embla__viewport" ref="emblaNode">
|
||
|
<div class="embla__container">
|
||
|
<div class="embla__slide" v-for="(slide, index) in slides" :key="index">
|
||
|
<img :src="slide" alt="" />
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<!-- 左右箭头 -->
|
||
|
<button class="embla__button prev" @click="scrollPrev" :disabled="!canScrollPrev">‹</button>
|
||
|
<button class="embla__button next" @click="scrollNext" :disabled="!canScrollNext">›</button>
|
||
|
|
||
|
<!-- 圆点导航 -->
|
||
|
<div class="embla__dots">
|
||
|
<button
|
||
|
v-for="(_, index) in slides"
|
||
|
:key="index"
|
||
|
:class="{ 'is-selected': state.selectedIndex == index }"
|
||
|
@click="scrollTo(index)"
|
||
|
>
|
||
|
{{}}
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script setup>
|
||
|
import { onMounted, ref, reactive } from 'vue'
|
||
|
import EmblaCarousel from 'embla-carousel'
|
||
|
|
||
|
const emblaNode = ref(null)
|
||
|
const embla = ref(null)
|
||
|
|
||
|
const state = reactive({
|
||
|
selectedIndex: 0,
|
||
|
canScrollPrev: false,
|
||
|
canScrollNext: false,
|
||
|
})
|
||
|
|
||
|
const slides = ['/images/banner/bk1000.png', '/images/banner/bk2000.png']
|
||
|
|
||
|
const updateButtons = () => {
|
||
|
if (!embla.value) return
|
||
|
state.canScrollPrev = embla.value.canScrollPrev()
|
||
|
state.canScrollNext = embla.value.canScrollNext()
|
||
|
state.selectedIndex = embla.value.selectedScrollSnap()
|
||
|
}
|
||
|
|
||
|
const scrollPrev = () => embla.value?.scrollPrev()
|
||
|
const scrollNext = () => embla.value?.scrollNext()
|
||
|
const scrollTo = index => embla.value?.scrollTo(index)
|
||
|
|
||
|
onMounted(() => {
|
||
|
embla.value = EmblaCarousel(emblaNode.value, { loop: true })
|
||
|
|
||
|
const updateOnSelect = () => {
|
||
|
state.selectedIndex = embla.value.selectedScrollSnap()
|
||
|
state.canScrollPrev = embla.value.canScrollPrev()
|
||
|
state.canScrollNext = embla.value.canScrollNext()
|
||
|
}
|
||
|
|
||
|
embla.value.on('select', updateOnSelect)
|
||
|
})
|
||
|
</script>
|
||
|
|
||
|
<style scoped>
|
||
|
.embla {
|
||
|
position: relative;
|
||
|
}
|
||
|
.embla__viewport {
|
||
|
overflow: hidden;
|
||
|
}
|
||
|
.embla__container {
|
||
|
display: flex;
|
||
|
}
|
||
|
.embla__slide {
|
||
|
flex: 0 0 100%;
|
||
|
padding: 10px;
|
||
|
}
|
||
|
.embla__button {
|
||
|
position: absolute;
|
||
|
top: 50%;
|
||
|
transform: translateY(-50%);
|
||
|
background: #00000088;
|
||
|
color: white;
|
||
|
border: none;
|
||
|
padding: 10px;
|
||
|
cursor: pointer;
|
||
|
z-index: 1;
|
||
|
}
|
||
|
.embla__button.prev {
|
||
|
left: 10px;
|
||
|
}
|
||
|
.embla__button.next {
|
||
|
right: 10px;
|
||
|
}
|
||
|
.embla__dots {
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
gap: 8px;
|
||
|
margin-top: 10px;
|
||
|
}
|
||
|
.embla__dots button {
|
||
|
width: 10px;
|
||
|
height: 10px;
|
||
|
border-radius: 50%;
|
||
|
border: none;
|
||
|
background: #ccc;
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
.embla__dots .is-selected {
|
||
|
background: #333;
|
||
|
}
|
||
|
</style>
|