@ -0,0 +1,87 @@ |
|||||
|
<template> |
||||
|
<view class="music-control" @click="toggleMusic"> |
||||
|
<text class="music-text" :class="{ 'rotating': isPlaying }"> |
||||
|
{{ isPlaying ? '🎵' : '🔇' }} |
||||
|
</text> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: 'MusicControl', |
||||
|
data() { |
||||
|
return { |
||||
|
isPlaying: false |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
// 组件挂载时同步音乐状态 |
||||
|
this.syncMusicState(); |
||||
|
|
||||
|
// 添加定时器,每秒同步一次状态 |
||||
|
this.timer = setInterval(() => { |
||||
|
this.syncMusicState(); |
||||
|
}, 1000); |
||||
|
}, |
||||
|
beforeUnmount() { |
||||
|
// 组件卸载前清除定时器 |
||||
|
if (this.timer) { |
||||
|
clearInterval(this.timer); |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
syncMusicState() { |
||||
|
const app = getApp(); |
||||
|
if (app && app.globalData) { |
||||
|
this.isPlaying = app.globalData.isMusicPlaying; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
toggleMusic() { |
||||
|
const app = getApp(); |
||||
|
if (!app || !app.globalData || !app.globalData.bgMusic) { |
||||
|
console.error('背景音乐未初始化'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const bgMusic = app.globalData.bgMusic; |
||||
|
|
||||
|
// 直接基于当前组件的状态切换 |
||||
|
if (this.isPlaying) { |
||||
|
bgMusic.pause(); |
||||
|
} else { |
||||
|
bgMusic.play(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.music-control { |
||||
|
position: fixed; |
||||
|
right: 30rpx; |
||||
|
bottom: 30rpx; |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
border-radius: 50%; |
||||
|
background-color: rgba(0, 0, 0, 0.3); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
z-index: 999; |
||||
|
} |
||||
|
|
||||
|
.music-text { |
||||
|
font-size: 40rpx; |
||||
|
} |
||||
|
|
||||
|
.rotating { |
||||
|
animation: rotate 3s linear infinite; |
||||
|
} |
||||
|
|
||||
|
@keyframes rotate { |
||||
|
from { transform: rotate(0deg); } |
||||
|
to { transform: rotate(360deg); } |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,97 @@ |
|||||
|
<template> |
||||
|
<view v-if="visible" class="share-guide-mask" @click="closeGuide"> |
||||
|
<view class="guide-content"> |
||||
|
<image class="guide-arrow" :src="arrowImage" mode=""></image> |
||||
|
<view v-for="(text, index) in textArray" :key="index" class="guide-text"> |
||||
|
{{ text }} |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
props: { |
||||
|
value: { |
||||
|
type: Boolean, |
||||
|
default: false |
||||
|
}, |
||||
|
text: { |
||||
|
type: [String, Array], |
||||
|
default: '点击右上角"..."选择"分享到朋友圈"' |
||||
|
}, |
||||
|
arrowImage: { |
||||
|
type: String, |
||||
|
default: '/static/share-arrow.png' |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
visible: { |
||||
|
get() { |
||||
|
return this.value; |
||||
|
}, |
||||
|
set(val) { |
||||
|
this.$emit('input', val); |
||||
|
} |
||||
|
}, |
||||
|
textArray() { |
||||
|
if (Array.isArray(this.text)) { |
||||
|
return this.text; |
||||
|
} |
||||
|
return [this.text]; |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
closeGuide() { |
||||
|
this.visible = false; |
||||
|
this.$emit('close'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.share-guide-mask { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, 0.7); |
||||
|
z-index: 9999; |
||||
|
display: flex; |
||||
|
justify-content: flex-end; |
||||
|
align-items: flex-start; |
||||
|
} |
||||
|
|
||||
|
.guide-content { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
padding-top: 100rpx; |
||||
|
padding-right: 60rpx; |
||||
|
} |
||||
|
|
||||
|
.guide-arrow { |
||||
|
width: 100rpx; |
||||
|
height: 160rpx; |
||||
|
animation: arrow-up 1s infinite alternate; |
||||
|
} |
||||
|
|
||||
|
.guide-text { |
||||
|
font-size: 32rpx; |
||||
|
color: #FFFFFF; |
||||
|
font-weight: bold; |
||||
|
margin-bottom: 10rpx; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
@keyframes arrow-up { |
||||
|
from { |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
to { |
||||
|
transform: translateY(-15rpx); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,68 @@ |
|||||
|
<template> |
||||
|
<image v-if="selectedItem" :src="selectedItem.image" class="random-image" mode="" /> |
||||
|
<view v-if="selectedItem" class="random-image-name"> |
||||
|
{{selectedItem.name}} |
||||
|
</view> |
||||
|
<view v-if="selectedItem" class="random-image-desc"> |
||||
|
{{selectedItem.desc}} |
||||
|
</view> |
||||
|
<MusicControl /> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
images: { |
||||
|
type: Array, |
||||
|
required: true |
||||
|
} |
||||
|
}) |
||||
|
const selectedItem = ref(null) |
||||
|
|
||||
|
// 随机选择一项 |
||||
|
const selectRandomImage = () => { |
||||
|
if (props.images && props.images.length > 0) { |
||||
|
const randomIndex = Math.floor(Math.random() * props.images.length) |
||||
|
selectedItem.value = props.images[randomIndex] |
||||
|
} |
||||
|
} |
||||
|
onMounted(() => { |
||||
|
selectRandomImage() |
||||
|
}) |
||||
|
defineExpose({ |
||||
|
selectRandomImage, |
||||
|
selectedItem |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.random-image { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.random-image-name { |
||||
|
position: absolute; |
||||
|
bottom: 30%; |
||||
|
left: 50%; |
||||
|
transform: translate(-50%, -50%); |
||||
|
color: #ffffff; |
||||
|
font-size: 52rpx; |
||||
|
} |
||||
|
|
||||
|
.random-image-desc { |
||||
|
white-space: nowrap; |
||||
|
position: absolute; |
||||
|
bottom: 25%; |
||||
|
left: 50%; |
||||
|
transform: translate(-50%, -50%); |
||||
|
color: #ffffff; |
||||
|
font-size: 24rpx; |
||||
|
font-weight: 300; |
||||
|
opacity: .8; |
||||
|
} |
||||
|
</style> |
After Width: | Height: | Size: 27 MiB |
After Width: | Height: | Size: 18 MiB |
After Width: | Height: | Size: 31 MiB |
After Width: | Height: | Size: 35 MiB |
After Width: | Height: | Size: 28 MiB |
After Width: | Height: | Size: 27 MiB |
After Width: | Height: | Size: 19 MiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 1.9 MiB |
After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 226 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 1.5 MiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 264 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 180 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.9 MiB |
After Width: | Height: | Size: 183 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 743 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 243 KiB |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 152 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 128 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 2.5 MiB |
After Width: | Height: | Size: 4.5 MiB |
After Width: | Height: | Size: 4.5 MiB |
After Width: | Height: | Size: 4.1 MiB |
After Width: | Height: | Size: 3.5 MiB |
After Width: | Height: | Size: 3.0 MiB |
After Width: | Height: | Size: 3.2 MiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 4.2 MiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 1.7 MiB |
After Width: | Height: | Size: 169 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 1.5 MiB |
After Width: | Height: | Size: 162 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 1.7 MiB |
After Width: | Height: | Size: 182 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 1.5 MiB |
After Width: | Height: | Size: 162 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 1.5 MiB |
After Width: | Height: | Size: 170 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 1.6 MiB |
After Width: | Height: | Size: 163 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 1.5 MiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 851 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 16 MiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 3.3 MiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 4.4 MiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 17 MiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 4.6 MiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 15 MiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 15 MiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 10 KiB |