参考文档
效果如下图
- 使用
<swiper>
实现轮播组件,创建 Carousel.vue
轮播组件:
<script setup lang="ts">
import Taro from '@tarojs/taro'
import { ref, computed } from 'vue'
interface Image {
title?: string // 图片名称
src: string // 图片地址
link?: string // 图片跳转链接
}
interface Props {
images: Image[] // 图片数组
height?: number|string // 走马灯宽度
mode?: string // 图片裁剪、缩放的模式,与微信小程序 <image> 标签 mode 属性一致
autoplay?: boolean // 是否自动切换
circular?: boolean // 是否采用衔接滑动
vertical?: boolean // 滑动方向是否为纵向
interval?: number // 自动切换时间间隔
duration?: number // 滑动动画时长
easingFunction?: 'default'|'linear'|'easeInCubic'|'easeOutCubic'|'easeInOutCubic' // 默认缓动函数 线性动画 缓入动画 缓出动画 缓入缓出动画
indicatorDots?: boolean // 是否显示面板指示点
indicatorColor?: string // 指示点颜色
indicatorActiveColor?: string // 当前选中的指示点颜色
isPreview?: boolean // 是否开启图片预览
}
const props = withDefaults(defineProps<Props>(), {
images: () => [],
height: 'calc(100vh - 100rpx - env(safe-area-inset-bottom))',
mode: 'aspectFill', // 缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
autoplay: true,
circular: true,
vertical: false,
interval: 3000,
duration: 1000,
easingFunction: 'easeInOutCubic',
indicatorDots: true,
indicatorColor: 'rgba(0, 0, 0, .3)',
indicatorActiveColor: '#1677FF', // #000000
isPreview: false
})
const CarouselHeight = computed(() => {
if (typeof props.height === 'number') {
return props.height + 'rpx'
}
return props.height
})
function onRoute (url: string) {
Taro.navigateTo({
url: url
})
}
const showPreview = ref(false)
const showIndex = ref(0)
function onPreview (index: number) {
showIndex.value = index
showPreview.value = true
}
function onClose () {
showPreview.value = false
}
</script>
<template>
<swiper
:style="`height: ${CarouselHeight};`"
:interval="interval"
:autoplay="autoplay"
:circular="circular"
:vertical="vertical"
:duration="duration"
:easingFunction="easingFunction"
:indicator-dots="indicatorDots"
:indicator-color="indicatorColor"
:indicator-active-color="indicatorActiveColor"
v-bind="$attrs">
<swiper-item v-for="(image, index) in images" :key="index">
<view class="m-image" @tap="image.link ? onRoute(image.link) : () => false">
<image @tap="isPreview ? onPreview(index) : () => false" class="u-image" :src="image.src" :mode="mode" />
</view>
</swiper-item>
</swiper>
<nut-image-preview
:init-no="showIndex"
:show="showPreview"
:images="props.images"
is-Loop
pagination-visible
closeable
close-icon-position="top-left"
@close="onClose" />
</template>
<style lang="less">
.m-image {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.u-image {
width: 100%;
height: 100%;
}
}
</style>
- 使用
<nut-swiper>
实现轮播组件,创建 NutCarousel.vue
轮播组件:
<script setup lang="ts">
import Taro from '@tarojs/taro'
import { ref, computed } from 'vue'
interface Image {
title?: string // 图片名称
src: string // 图片地址
link?: string // 图片跳转链接
}
interface Props {
images: Image[] // 图片数组
height?: number|string // 轮播卡片的高度
direction?: 'horizontal'|'vertical' // 轮播方向
mode?: string // 图片裁剪、缩放的模式,与微信小程序 <image> 标签 mode 属性一致
loop?: boolean // 是否循环轮播
duration?: number|string // 动画时长(单位是 ms)
autoPlay?: number|string // 自动轮播时长,0 表示不会自动轮播
initPage?: number|string // 初始化索引值
touchable?: boolean // 是否可触摸滑动
paginationVisible?: boolean // 分页指示器是否展示
paginationUnselectedColor?: string // 分页指示器没有选中的颜色
paginationColor?: string // 分页指示器选中的颜色
isPreview?: boolean // 是否开启图片预览
}
const props = withDefaults(defineProps<Props>(), {
images: () => [],
height: 'calc(100vh - 100rpx - env(safe-area-inset-bottom))',
direction: 'horizontal',
mode: 'aspectFill', // 缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
loop: true,
duration: 500,
autoPlay: 3000,
initPage: 0,
touchable: true,
paginationVisible: true,
paginationUnselectedColor: 'rgba(0, 0, 0, .3)',
paginationColor: '#FF5B29',
isPreview: false
})
const CarouselHeight = computed(() => {
if (typeof props.height === 'number') {
return props.height + 'rpx'
}
return props.height
})
function onRoute (url: string) {
Taro.navigateTo({
url: url
})
}
const showPreview = ref(false)
const showIndex = ref(0)
function onPreview (index: number) {
showIndex.value = index
showPreview.value = true
}
function onClose () {
showPreview.value = false
}
</script>
<template>
<nut-swiper
:style="`height: ${CarouselHeight};`"
:direction="direction"
:loop="loop"
:duration="duration"
:auto-play="autoPlay"
:init-page="initPage"
:touchable="touchable"
:pagination-visible="paginationVisible"
:pagination-unselected-color="paginationUnselectedColor"
:pagination-color="paginationColor"
v-bind="$attrs">
<nut-swiper-item v-for="(image, index) in images" :key="index">
<view class="m-image" @tap="image.link ? onRoute(image.link) : () => false">
<image @tap="isPreview ? onPreview(index) : () => false" class="u-image" :src="image.src" :mode="mode" />
</view>
</nut-swiper-item>
</nut-swiper>
<nut-image-preview
:init-no="showIndex"
:show="showPreview"
:images="props.images"
is-Loop
pagination-visible
closeable
close-icon-position="top-left"
@close="onClose" />
</template>
<style lang="less">
.nut-swiper-pagination .h5-i {
width: 48px;
height: 10px;
border-radius: 6px;
&:not(:last-child) {
margin-right: 20px;
}
}
.m-image {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.u-image {
width: 100%;
height: 100%;
}
}
</style>
<script setup lang="ts">
import { ref } from 'vue'
import Carousel from '@/components/Carousel.vue'
// import NutCarousel from '@/components/NutCarousel.vue'
const images = ref([
{
src: 'https://digitalassets.tesla.com/tesla-contents/image/upload/f_auto,q_auto/Homepage-Model-Y-Mobile-CN-v2.png'
},
{
src: 'https://digitalassets.tesla.com/tesla-contents/image/upload/f_auto,q_auto/Homepage-Model-3-Mobile-LHD-v2.jpg'
},
{
src: 'https://digitalassets.tesla.com/tesla-contents/image/upload/h_1624,w_750,c_fit,f_auto,q_auto:best/Model-S-homepage-mobile'
},
{
src: 'https://digitalassets.tesla.com/tesla-contents/image/upload/h_1700,w_800,c_fit,f_auto,q_auto:best/Homepage-Model-X-Mobile-LHD_001'
}
])
</script>
<template>
<Carousel :images="images" />
<!-- <NutCarousel :images="images" /> -->
</template>