2025-07-31 17:26:06 +08:00
|
|
|
<template>
|
|
|
|
<view>
|
|
|
|
<image :src="isError ? defaultImage : links[currentIndex]" :style="{ width: width, height: height }"
|
|
|
|
:mode="objectFit" @error="isError = true" @load="isError = false" />
|
|
|
|
<button v-if="showButton" @click="$emit('update:playing', !playing)">
|
|
|
|
{{ playing ? '停止播放' : '开始播放' }}
|
|
|
|
</button>
|
|
|
|
</view>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
import {
|
|
|
|
ref,
|
|
|
|
watch,
|
|
|
|
onUnmounted
|
|
|
|
} from 'vue'
|
|
|
|
|
|
|
|
// 定义组件的 props
|
|
|
|
const props = defineProps({
|
|
|
|
links: {
|
|
|
|
type: Array,
|
|
|
|
default: () => []
|
|
|
|
},
|
|
|
|
width: {
|
|
|
|
type: String,
|
2025-08-13 17:19:40 +08:00
|
|
|
default: '65rpx'
|
2025-07-31 17:26:06 +08:00
|
|
|
},
|
|
|
|
height: {
|
|
|
|
type: String,
|
2025-08-13 17:19:40 +08:00
|
|
|
default: '65rpx'
|
2025-07-31 17:26:06 +08:00
|
|
|
},
|
|
|
|
objectFit: {
|
|
|
|
type: String,
|
|
|
|
default: 'aspectFill'
|
|
|
|
},
|
|
|
|
defaultImage: {
|
|
|
|
type: String,
|
|
|
|
default: ''
|
|
|
|
},
|
|
|
|
interval: {
|
|
|
|
type: Number,
|
|
|
|
default: 80
|
|
|
|
},
|
|
|
|
playing: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
showButton: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
loop: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// 定义组件发出的事件
|
|
|
|
const emit = defineEmits(['update:playing'])
|
|
|
|
|
|
|
|
// 组件内部状态
|
|
|
|
const currentIndex = ref(0) // 当前播放的图片索引
|
|
|
|
const isPlaying = ref(false) // 是否正在播放
|
|
|
|
const isError = ref(false) // 当前图片是否加载失败
|
|
|
|
let timer = null // 定时器
|
|
|
|
|
|
|
|
// 开始播放
|
|
|
|
const startPlay = () => {
|
|
|
|
if (isPlaying.value) return
|
|
|
|
isPlaying.value = true
|
|
|
|
timer = setInterval(() => {
|
|
|
|
if (props.loop) {
|
|
|
|
// 循环播放:使用模运算循环索引
|
|
|
|
currentIndex.value = (currentIndex.value + 1) % props.links.length
|
|
|
|
isError.value = false
|
|
|
|
} else {
|
|
|
|
// 非循环播放:到末尾时停止
|
|
|
|
if (currentIndex.value < props.links.length - 1) {
|
|
|
|
currentIndex.value++
|
|
|
|
isError.value = false
|
|
|
|
} else {
|
|
|
|
stopPlay()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, props.interval)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 停止播放
|
|
|
|
const stopPlay = () => {
|
|
|
|
isPlaying.value = false
|
|
|
|
clearInterval(timer)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 监听 playing 属性变化
|
|
|
|
watch(() => props.playing, (val) => {
|
|
|
|
currentIndex.value = 0
|
|
|
|
if (val) {
|
|
|
|
startPlay()
|
|
|
|
} else {
|
|
|
|
stopPlay()
|
|
|
|
setTimeout(() => currentIndex.value = 0, 50)
|
|
|
|
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// 监听 links 数组变化
|
|
|
|
watch(() => props.links, () => {
|
|
|
|
currentIndex.value = 0
|
|
|
|
isError.value = false
|
|
|
|
if (isPlaying.value) {
|
|
|
|
stopPlay()
|
|
|
|
}
|
|
|
|
}, {
|
|
|
|
deep: true
|
|
|
|
})
|
|
|
|
|
|
|
|
// 组件销毁时清理定时器
|
|
|
|
onUnmounted(() => {
|
|
|
|
stopPlay()
|
|
|
|
})
|
|
|
|
</script>
|