113 lines
2.1 KiB
Vue
113 lines
2.1 KiB
Vue
<template>
|
|
<view class="volume-control">
|
|
<view class="volume-icon" @click="toggleMute">
|
|
<text class="icon">{{ isMuted ? '🔇' : '🔊' }}</text>
|
|
</view>
|
|
|
|
<view v-if="showSlider" class="volume-slider-wrapper">
|
|
<slider
|
|
class="volume-slider"
|
|
:value="currentVolume"
|
|
:min="0"
|
|
:max="100"
|
|
@change="handleVolumeChange"
|
|
@changing="handleVolumeChanging"
|
|
activeColor="#1989fa"
|
|
backgroundColor="rgba(255, 255, 255, 0.3)"
|
|
block-size="12"
|
|
/>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, watch } from 'vue'
|
|
|
|
interface Props {
|
|
volume: number
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
volume: 100
|
|
})
|
|
|
|
const emit = defineEmits<{
|
|
change: [volume: number]
|
|
}>()
|
|
|
|
const showSlider = ref(false)
|
|
const currentVolume = ref(props.volume)
|
|
const isMuted = ref(false)
|
|
const volumeBeforeMute = ref(props.volume)
|
|
|
|
watch(
|
|
() => props.volume,
|
|
(newVolume) => {
|
|
currentVolume.value = newVolume
|
|
isMuted.value = newVolume === 0
|
|
}
|
|
)
|
|
|
|
const toggleMute = () => {
|
|
if (isMuted.value) {
|
|
// 取消静音
|
|
const volume = volumeBeforeMute.value || 50
|
|
currentVolume.value = volume
|
|
emit('change', volume)
|
|
isMuted.value = false
|
|
} else {
|
|
// 静音
|
|
volumeBeforeMute.value = currentVolume.value
|
|
currentVolume.value = 0
|
|
emit('change', 0)
|
|
isMuted.value = true
|
|
}
|
|
}
|
|
|
|
const handleVolumeChange = (e: any) => {
|
|
const volume = e.detail.value
|
|
currentVolume.value = volume
|
|
isMuted.value = volume === 0
|
|
emit('change', volume)
|
|
}
|
|
|
|
const handleVolumeChanging = (e: any) => {
|
|
currentVolume.value = e.detail.value
|
|
}
|
|
|
|
// 点击音量图标时切换滑块显示
|
|
const toggleSlider = () => {
|
|
showSlider.value = !showSlider.value
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.volume-control {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10rpx;
|
|
position: relative;
|
|
}
|
|
|
|
.volume-icon {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
|
|
.icon {
|
|
font-size: 36rpx;
|
|
}
|
|
}
|
|
|
|
.volume-slider-wrapper {
|
|
width: 150rpx;
|
|
}
|
|
|
|
.volume-slider {
|
|
width: 100%;
|
|
}
|
|
</style>
|