赞
踩
参考文档:
本文使用版本:Swiper@11.0.5
安装插件:pnpm i swiper
本文基于Swiper插件进行封装,主要实现两种形式的轮播图展示:
首页轮播图切换展示(type: banner)
走马灯轮播图滚动展示(type: carousel)
信息展播模式(type: broadcast)
可自定义设置以下属性:
轮播图片数组(images),类型:Array<{title: string, link?: string, src: string}>,默认 []
图片宽度(width),类型:number | string,默认 '100%'
图片高度(height),类型:number | string,默认 '100vh'
banner轮播图模式 | carousel走马灯模式(type),类型:'banner'|'carouse'|'broadcast',默认 'banner'
是否显示导航(navigation),类型:boolean,默认 true
自动切换的时间间隔(type: banner时生效)(delay),单位ms,类型:number,默认 3000
是否可以鼠标拖动(swipe),类型:boolean,默认 true
预加载时的loading颜色(preloaderColor),类型:'theme'|'white'|'black',默认 'theme',可选 theme(主题色) | white | black
效果如下图:在线预览
首页轮播图 type: banner
走马灯 type: carousel
信息展播 type: broadcast
①创建触摸滑动组件Swiper.vue:
- <script setup lang="ts">
- import { Swiper, SwiperSlide } from 'swiper/vue'
- import { Pagination, Navigation, Autoplay, EffectFade, Mousewheel } from 'swiper/modules'
- import 'swiper/css'
- import 'swiper/css/navigation'
- import 'swiper/css/pagination'
- import 'swiper/css/effect-fade'
- import { ref, computed } from 'vue'
- interface Image {
- title: string // 图片名称
- link?: string // 图片跳转链接
- src: string // 图片地址
- }
- interface Props {
- images: Image[] // 轮播图片数组
- width?: number|string // 图片宽度
- height?: number|string // 图片高度
- type?: 'banner'|'carousel'|'broadcast' // banner轮播图模式 | carousel走马灯模式
- navigation?: boolean // 是否显示导航
- delay?: number // 自动切换的时间间隔(type: banner时生效),单位ms
- swipe?: boolean // 是否可以鼠标拖动
- preloaderColor?: 'theme'|'white'|'black' // 预加载时的loading颜色
- }
- const props = withDefaults(defineProps<Props>(), {
- images: () => [],
- width: '100%',
- height: '100vh',
- type: 'banner', // 可选 banner | carousel
- navigation: true,
- delay: 3000,
- swipe: true,
- preloaderColor: 'theme' // 可选 theme white black
- })
- const imgWidth = computed(() => {
- if (typeof props.width === 'number') {
- return props.width + 'px'
- } else {
- return props.width
- }
- })
- const imgHeight = computed(() => {
- if (typeof props.height === 'number') {
- return props.height + 'px'
- } else {
- return props.height
- }
- })
- const modulesBanner = ref([Navigation, Pagination, Autoplay, EffectFade])
- const autoplayBanner = ref({
- delay: props.delay,
- disableOnInteraction: false, // 用户操作swiper之后,是否禁止autoplay。默认为true:停止。
- pauseOnMouseEnter: true // 鼠标置于swiper时暂停自动切换,鼠标离开时恢复自动切换,默认false
- })
-
- const modulesCarousel = ref([Autoplay])
- const autoplayCarousel = ref<object|boolean>({
- delay: 0,
- disableOnInteraction: false
- })
- const modulesBroadcast = ref([Navigation, Pagination, Mousewheel])
- const emits = defineEmits(['swiper', 'change'])
- function onSwiper (swiper: any) {
- // console.log(swiper)
- emits('swiper', swiper)
- if (props.type === 'carousel') {
- swiper.el.onmouseenter = () => { // 移入暂停
- swiper.autoplay.stop()
- }
- swiper.el.onmouseleave = () => { // 移出启动
- swiper.autoplay.start()
- }
- }
- }
- </script>
- <template>
- <swiper
- v-if="type==='banner'"
- :class="{'swiper-no-swiping': !swipe}"
- :modules="modulesBanner"
- :navigation="navigation"
- :slides-per-view="1"
- :autoplay="autoplayBanner"
- lazy
- loop
- @swiper="onSwiper"
- @slideChange="$emit('change')"
- v-bind="$attrs">
- <swiper-slide v-for="(image, index) in images" :key="index">
- <a :href="image.link ? image.link:'javascript:;'" :target="image.link ? '_blank':'_self'" class="m-link">
- <img
- :src="image.src"
- class="u-img"
- :style="`width: ${imgWidth}; height: ${imgHeight};`"
- :alt="image.title"
- loading="lazy" />
- </a>
- <div :class="`swiper-lazy-preloader swiper-lazy-preloader-${preloaderColor}`"></div>
- </swiper-slide>
- </swiper>
- <swiper
- v-if="type==='carousel'"
- class="swiper-no-swiping"
- :modules="modulesCarousel"
- :autoplay="autoplayCarousel"
- lazy
- loop
- @swiper="onSwiper"
- @slideChange="$emit('change')"
- v-bind="$attrs">
- <swiper-slide v-for="(image, index) in images" :key="index">
- <a :href="image.link ? image.link:'javascript:;'" :target="image.link ? '_blank':'_self'" class="m-link">
- <img
- :src="image.src"
- class="u-img"
- :style="`width: ${imgWidth}; height: ${imgHeight};`"
- :alt="image.title"
- loading="lazy" />
- </a>
- <div :class="`swiper-lazy-preloader swiper-lazy-preloader-${preloaderColor}`"></div>
- </swiper-slide>
- </swiper>
- <swiper
- v-if="type==='broadcast'"
- :modules="modulesBroadcast"
- :navigation="navigation"
- lazy
- @swiper="onSwiper"
- @slideChange="$emit('change')"
- v-bind="$attrs">
- <swiper-slide v-for="(image, index) in images" :key="index">
- <a :href="image.link ? image.link:'javascript:;'" :target="image.link ? '_blank':'_self'" class="m-link">
- <img
- :src="image.src"
- class="u-img"
- :style="`width: ${imgWidth}; height: ${imgHeight};`"
- :alt="image.title"
- loading="lazy" />
- </a>
- <div :class="`swiper-lazy-preloader swiper-lazy-preloader-${preloaderColor}`"></div>
- </swiper-slide>
- </swiper>
- </template>
- <style lang="less" scoped>
- .m-link {
- display: block;
- height: 100%;
- }
- .u-img {
- object-fit: cover;
- cursor: pointer;
- }
- .swiper {
- --swiper-theme-color: @themeColor;
- }
- :deep(.swiper-wrapper) { // 自动切换过渡效果设置
- transition-timing-function: linear; // 线性过渡模拟走马灯效果
- -webkit-transition-timing-function: linear;
- }
- :deep(.swiper-pagination-bullet) {
- width: 12px;
- height: 12px;
- }
- .swiper-lazy-preloader-theme {
- --swiper-preloader-color: @themeColor;
- }
- </style>
②在要使用的页面引入:
- <script setup lang="ts">
- import Swiper from './Swiper.vue'
- import pkg from '/package.json'
- import { ref, shallowReactive, onBeforeMount } from 'vue'
-
- const images = ref<any[]>([])
- function loadImages () {
- for (let i = 1; i <= 10; i++) {
- images.value.push({
- title: `image-${i}`,
- link: `https://cdn.jsdelivr.net/gh/themusecatcher/resources@0.0.5/${i}.jpg`,
- src: `https://cdn.jsdelivr.net/gh/themusecatcher/resources@0.0.5/${i}.jpg`
- })
- }
- }
- onBeforeMount(() => { // 组件已完成响应式状态设置,但未创建DOM节点
- loadImages()
- })
- function onChange () {
- console.log('slider change')
- }
- const navigation = shallowReactive<{[key: string]: any}>({})
- function onSwiper (swiper: any) {
- navigation.prevEl = swiper.navigation.prevEl
- navigation.prevEl.style.display = 'none'
- navigation.nextEl = swiper.navigation.nextEl
- navigation.nextEl.style.display = 'none'
- }
- function onPrev () {
- navigation.prevEl.click()
- }
- function onNext () {
- navigation.nextEl.click()
- }
- </script>
- <template>
- <div>
- <h1>Swiper 参考文档</h1>
- <ul class="m-list">
- <li>
- <a class="u-file" href="https://swiperjs.com/" target="_blank">Swiper官方</a>
- </li>
- <li>
- <a class="u-file" href="https://swiperjs.com/swiper-api" target="_blank">Swiper API</a>
- </li>
- <li>
- <a class="u-file" href="https://swiperjs.com/vue" target="_blank">Swiper Vue</a>
- </li>
- <li>
- <a class="u-file" href="https://swiperjs.com/demos" target="_blank">Swiper Demos</a>
- </li>
- </ul>
- <Space align="top" class="mt30" :size="6">
- <h1>Swiper</h1>
- <Tag color="volcano">{{ pkg.dependencies.swiper }}</Tag>
- </Space>
- <h2 class="mt30 mb10">基本使用</h2>
- <Swiper
- :images="images"
- :height="600"
- :pagination="{
- dynamicBullets: true,
- clickable: true
- }"
- @change="onChange" />
- <h2 class="mt30 mb10">走马灯</h2>
- <Swiper
- :images="images"
- type="carousel"
- :height="240"
- :slides-per-view="3"
- :space-between="20"
- :speed="2500" />
- <h2 class="mt30 mb10">信息展播</h2>
- <Space>
- <Button @click="onPrev">Prev</Button>
- <Button @click="onNext">Next</Button>
- </Space>
- <br/>
- <br/>
- <Swiper
- :images="images"
- type="broadcast"
- :pagination="{
- dynamicBullets: true,
- clickable: true
- }"
- :height="320"
- :slides-per-view="3"
- :space-between="30"
- loop
- mousewheel
- @swiper="onSwiper" />
- </div>
- </template>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。