mindboost-rnbo-test-project/components/sliders/MusicGainSlider.vue

236 lines
5.3 KiB
Vue

<template>
<div class="slider-wrapper">
<!-- Slot for passing any audio element -->
<img
v-if="volumeValue == 0"
style="width: 25px; height: 25px;"
src="~/assets/image/music_muted.svg"
:title="t('unmuteSlider')"
@click="toggleMute()"
>
<img
v-else
style="width: 25px; height: 25px;"
src="~/assets/image/music.svg"
:title="t('muteSlider')"
@click="toggleMute()"
>
<div class="slider">
<input
id="gain-control-music"
ref="MusicSlider"
type="range"
min="0"
max="1"
step="0.001"
data-toggle="tooltip"
data-placement="top"
:title="t('textSlider')"
@input="changeVolumeOnTrack"
@wheel.prevent="changeVolumeOnWheel"
>
<span
class="slider-progress-bar"
:style="{ width: `${volumeValue * 100}%` }"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch, computed } from 'vue'
import { useAudioStore } from '~/stores/audio'
const MusicSlider = ref(null)
const audioStore = useAudioStore()
const { t } = useI18n()
// Computed volume value from the audio store
const volumeValue = computed(() => audioStore.getVolume)
// Stores volume before muting
let volumeOnMute = audioStore.getVolume
/**
* Toggles mute state:
* - If volume > 0: saves current volume and sets to 0
* - If volume == 0: restores saved volume
*/
const toggleMute = () => {
if (audioStore.getVolume !== 0) {
volumeOnMute = audioStore.getVolume
audioStore.setVolume(0)
} else {
audioStore.setVolume(volumeOnMute)
}
}
/**
* Syncs external slider DOM element with the reactive volume state
*/
watch(volumeValue, (newValue) => {
if (MusicSlider.value) {
const inputSlider = MusicSlider.value as HTMLInputElement
inputSlider.valueAsNumber = newValue
}
})
/**
* Handles scroll wheel changes over the slider element to increment/decrement volume.
* Clamped between 0 and 1 with 0.02 steps.
*
* @param {WheelEvent} event - Scroll event on the volume slider
*/
const changeVolumeOnWheel = (event: WheelEvent) => {
const deltaY = event.deltaY
if (deltaY < 0) {
const volumeAdd = Math.min(1, volumeValue.value + 0.02)
if (volumeAdd <= 1) { audioStore.setVolume(volumeAdd) }
} else {
const volumeCut = Math.max(0, volumeValue.value - 0.02)
if (volumeCut >= 0) { audioStore.setVolume(volumeCut) }
}
audioStore.setVolume(volumeValue.value)
}
/**
* Sets volume when user moves the range input (slider)
*
* @param {InputEvent} event - Input change from range slider
*/
const changeVolumeOnTrack = (event: InputEvent) => {
const target = event.target as HTMLInputElement
const volume = Number(target.value)
if (volume >= 0 && volume <= 1) {
audioStore.setVolume(volume)
}
}
</script>
<style>
.slider-wrapper{
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 1.5em;
}
.slider {
position: relative;
width: 100%;
margin: 1em auto;
}
.slider-icon {
cursor: pointer;
}
@media only screen and (max-width: 576px) {
.slider{
max-width: 80%;
}
}
.slider-progress-bar {
position: absolute;
height: 10px;
background-color: #e9c046;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border-radius: 5px;
left: 0;
z-index: 0;
}
/* Allgemeine Einstellungen für den Slider */
input[type="range"] {
-webkit-appearance: none; /* Entfernt das Standard-Styling in Webkit-Browsern */
appearance: none; /* Entfernt Standard-Styling in anderen Browsern */
width: 100%;
height: 10px;
background: #fff;
border-radius: 5px;
outline: none;
cursor: pointer;
position: absolute;
z-index:1;
left: 0;
}
/* Styling für den Track in Webkit-Browsern */
input[type="range"]::-webkit-slider-runnable-track {
height: 10px;
background: transparent;
border-radius: 5px;
position: relative;
z-index: 2;
}
/* Styling für den Thumb in Webkit-Browsern */
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 20px;
width: 20px;
background: #fff;
border-radius: 50%;
margin-top: -5px;
position: relative;
z-index: 10;
border: 2px solid #e9c046;
}
/* Styling für den Track in Firefox */
input[type="range"]::-moz-range-track {
height: 10px;
background: transparent;
border-radius: 5px;
position: relative;
z-index: 1;
}
/* Styling für den Thumb in Firefox */
input[type="range"]::-moz-range-thumb {
height: 20px;
width: 20px;
background-color: #e9c046;
border: none;
border-radius: 50%;
position: relative;
z-index: 1;
border: 2px solid #e9c046;
margin-top: -5px;
}
input[type="range"]::-moz-range-progress {
height: 10px;
background-color: #e9c046;
border-radius: 5px;
}
/* Styling für den Track in Internet Explorer/Edge */
input[type="range"]::-ms-track {
height: 10px;
background: transparent;
border-color: transparent;
color: transparent;
border-radius: 5px;
}
/* Styling für den Thumb in Internet Explorer/Edge */
input[type="range"]::-ms-thumb {
height: 20px;
width: 20px;
background: #f5f5f5;
border: none;
border-radius: 50%;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
position: relative;
z-index: 2;
border: 2px solid #e9c046;
}
/* Entfernt Ticks in IE */
input[type="range"]::-ms-ticks-after,
input[type="range"]::-ms-ticks-before {
display: none;
}
</style>