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.
116 lines
2.5 KiB
116 lines
2.5 KiB
<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>
|
|
|