I'm implementing a basic audio player using Svelte (version 4.2.8), with SVG images for the interface icons, but the play/pause icons are not updating as expected.
Stripped-down version of the code:
<script>
export let audioPath;
let audioElement, playButton, seekBar;
let currentlySeeking = false;
const checkForAudioSource = () => !!audioElement.getAttribute('src');
function togglePlayButton() {
if(checkForAudioSource()) {
if(audioElement.paused || audioElement.ended) audioElement.play();
else audioElement.pause();
}
}
// Seek bar event handling, from Develop HP: https://www.developphp.com/video/JavaScript/Audio-Seek-and-Volume-Range-Slider-Tutorial
const startSeeking = () => currentlySeeking = true;
function endSeeking() {
currentlySeeking = false;
if(checkForAudioSource()) audioElement.currentTime = Number(seekBar.value);
}
function updatePlayer() {
if(checkForAudioSource() && !currentlySeeking) seekBar.value = audioElement.currentTime.toString();
timeout = setTimeout(updatePlayer, 100);
}
onMount(() => updatePlayer());
</script>
<audio src={audioPath} preload="metadata" bind:this={audioElement}></audio>
<div id="audio-player">
<button on:click={togglePlayButton} bind:this={playButton}>
<img src={audioElement?.paused || audioElement?.ended ? "/svg/play.svg" : "/svg/pause.svg"} alt={audioElement?.paused || audioElement?.ended ? "Play" : "Pause"}>
</button>
<input type="range" value="0" step="0.1" on:mousedown={startSeeking} on:mouseup={endSeeking} bind:this={seekBar}>
</div>
Clicking the play/pause button does cause the audio file to play or pause as expected, and the seek bar updates as expected while playing and can be used to go to a specific moment in the sound file. However, the src
and alt
attributes of the play/pause button always remain "/svg/play.svg" and "Play" respectively, no matter when you click on the button (when the sound is at the beginning, the end, or in the middle).
I've tried doing some variations on the syntax of the event handling, but always got the same result. Is there something I'm missing here? Thanks so much in advance!
the src and alt attributes of the play/pause button always remain "/svg/play.svg" and "Play" respectively, no matter when you click on the button
Because Svelte's reactivity is triggered by assignments, and updating object properties won't trigger reactivity. source
after updating audioElement.paused
and audioElement.ended
, reassign audioElement
to itself.
audioElement = audioElement