Rumah > Artikel > hujung hadapan web > Ajar anda langkah demi langkah cara menulis pemain menggunakan Vue3
Artikel ini membawakan anda pengetahuan yang berkaitan tentang Vue3 terutamanya tentang cara menulis pemain dengan Vue3. Rakan yang berminat boleh melihatnya bersama-sama.
ps: Muzik mungkin gagal dimainkan. Sebabnya ialah pautan audio bersifat sementara dan boleh diganti secara manual.
TODO
Realisasikan main/jedacss
<template> <div class="song-item"> <audio src="" /> <!-- 进度条 --> <div class="audio-player"> <span>00:00</span> <div class="progress-wrapper"> <div class="progress-inner"> <div class="progress-dot" /> </div> </div> <span>00:00</span> <!-- 播放/暂停 --> <div style="margin-left: 10px; color: #409eff; cursor: pointer;" > 播放 </div> </div> </div></template><style lang="scss"> * { font-size: 14px; } .song-item { display: flex; flex-direction: column; justify-content: center; height: 100px; padding: 0 20px; transition: all ease .2s; border-bottom: 1px solid #ddd; /* 进度条样式 */ .audio-player { display: flex; height: 18px; margin-top: 10px; align-items: center; font-size: 12px; color: #666; .progress-wrapper { flex: 1; height: 4px; margin: 0 20px 0 20px; border-radius: 2px; background-color: #e9e9eb; cursor: pointer; .progress-inner { position: relative; width: 0%; height: 100%; border-radius: 2px; background-color: #409eff; .progress-dot { position: absolute; top: 50%; right: 0; z-index: 1; width: 10px; height: 10px; border-radius: 50%; background-color: #409eff; transform: translateY(-50%); } } } } }</style>Idea: Daftar acara klik untuk "Main ", dalam Dalam acara klik, gunakan atribut dan kaedah
Api kekunci:: Sama ada pemain semasa dijeda
audio
: Bermain
audio.paused
: Dijeda
audio.play()
audio.pause()
Akhir sekali, gunakan atribut dan acara pada templat.
const audioIsPlaying = ref(false); // 用于同步当前的播放状态const audioEle = ref<HTMLAudioElement | null>(null); // audio 元素/** * @description 播放/暂停音乐 */const togglePlayer = () => { if (audioEle.value) { if (audioEle.value?.paused) { audioEle.value.play(); audioIsPlaying.value = true; } else { audioEle.value?.pause(); audioIsPlaying.value = false; } } };onMounted(() => { // 页面点击的时候肯定是加载完成了,这里获取一下没毛病 audioEle.value = document.querySelector('audio'); });Realisasikan masa mula/tamat, masa mula dan bar skrol untuk mengikuti dinamik main balik secara dinamik
<div style="margin-left: 10px; color: #409eff; cursor: pointer;" @click="togglePlayer"> {{ audioIsPlaying ? '暂停' : '播放'}}</div>Idea: Dapatkan masa main semasa dan jumlah tempoh, dan kemudian dapatkan Tempoh semasa / jumlah tempoh dan peratusan main balik lagu ialah peratusan bar skrol. Dengan mendengar acara
Api kekunci:Api kunci:
: masa main balik semasa; 🎜>audio
timeupdate
: Acara ini akan dicetuskan apabila
berubah.
audio.currentTime
Sedari mengklik pada bar kemajuan untuk melompat ke kedudukan main balik yang ditentukan
audio.duration
Idea: daftarkan acara klik tetikus untuk bar skrol, dan dapatkan semasa satu setiap kali ia diklik
timeupdate
Dan lebar bar skrol, gunakan lebar /currentTime
Akhir sekali, gunakan jumlah tempoh * Hasil bagi sebelumnya akan mendapat kemajuan yang kita mahu, cuma kemas kini bar kemajuan sekali lagi.
import dayjs from 'dayjs';const audioCurrentPlayTime = ref('00:00'); // 当前播放时长const audioCurrentPlayCountTime = ref('00:00'); // 总时长const pgsInnerEle = ref<HTMLDivElement | null>(null);/** * @description 更新进度条与当前播放时间 */const updateProgress = () => { const currentProgress = audioEle.value!.currentTime / audioEle.value!.duration; pgsInnerEle.value!.style.width = `${currentProgress * 100}%`; // 设置进度时长 if (audioEle.value) audioCurrentPlayTime.value = dayjs(audioEle.value.currentTime * 1000).format('mm:ss'); };/** * @description 播放完成重置播放状态 */const audioPlayEnded = () => { audioCurrentPlayTime.value = '00:00'; pgsInnerEle.value!.style.width = '0%'; audioIsPlaying.value = false; };onMounted(() => { pgsInnerEle.value = document.querySelector('.progress-inner'); // 设置总时长 if (audioEle.value) audioCurrentPlayCountTime.value = dayjs(audioEle.value.duration * 1000).format('mm:ss'); // 侦听播放中事件 audioEle.value?.addEventListener('timeupdate', updateProgress, false); // 播放结束 event audioEle.value?.addEventListener('ended', audioPlayEnded, false); });: Koordinat x penuding tetikus berbanding objek yang mencetuskan acara.
koordinat tetikus dalam tetingkap, jarakIdea: Gunakan
offsetX
offsetX
Klik titik untuk menyeret bar skrol.untuk mengurus fungsi menyeret dan mendengar klik tetikus, pergerakan tetikus dan peristiwa angkat tetikus pada bar skrol ini. Apabila
diklik: Dapatkanevent.offsetX
/** * @description 点击滚动条同步更新音乐进度 */const clickProgressSync = (event: MouseEvent) => { if (audioEle.value) { // 保证是正在播放或者已经播放的状态 if (!audioEle.value.paused || audioEle.value.currentTime !== 0) { const pgsWrapperWidth = pgsWrapperEle.value!.getBoundingClientRect().width; const rate = event.offsetX / pgsWrapperWidth; // 同步滚动条和播放进度 audioEle.value.currentTime = audioEle.value.duration * rate; updateProgress(); } } };onMounted({ pgsWrapperEle.value = document.querySelector('.progress-wrapper'); // 点击进度条 event pgsWrapperEle.value?.addEventListener('mousedown', clickProgressSync, false); });// 别忘记统一移除侦听onBeforeUnmount(() => { audioEle.value?.removeEventListener('timeupdate', updateProgress); audioEle.value?.removeEventListener('ended', audioPlayEnded); pgsWrapperEle.value?.removeEventListener('mousedown', clickProgressSync); });titik dari tetingkap dan jarak pergerakan kanan maksimum (lebar bar tatal -
Apabila bergerak: Dapatkan
koordinat diperoleh apabila mengklik. Kemudian buat pertimbangan berdasarkan jarak pergerakan maksimum dan jangan biarkan ia melampaui batas. Akhir sekali: Jumlah tempoh * (tetingkap jarak titikhook
koordinat tetikus dalam tetingkap dalam masa nyata tolak+ dikira
x
/ panjang bar skrol) untuk mendapatkan peratusan untuk mengemas kini bar skrol dan kemajuanleft
Apabilaleft
dinaikkan: Tetapkan semulaflag
Tetapkan.
x
x
Akhirnya panggil inileft
x
[Cadangan berkaitan:
]flag
tutorial video vue.js
/** * @method useSongProgressDrag * @param audioEle * @param pgsWrapperEle * @param updateProgress 更新滚动条方法 * @param startSongDragDot 是否开启拖拽滚动 * @description 拖拽更新歌曲播放进度 */const useSongProgressDrag = ( audioEle: Ref<HTMLAudioElement | null>, pgsWrapperEle: Ref<HTMLDivElement | null>, updateProgress: () => void, startSongDragDot: Ref<boolean>) => { const audioPlayer = ref<HTMLDivElement | null>(null); const audioDotEle = ref<HTMLDivElement | null>(null); const dragFlag = ref(false); const position = ref({ startOffsetLeft: 0, startX: 0, maxLeft: 0, maxRight: 0, }); /** * @description 鼠标点击 audioPlayer */ const mousedownProgressHandle = (event: MouseEvent) => { if (audioEle.value) { if (!audioEle.value.paused || audioEle.value.currentTime !== 0) { dragFlag.value = true; position.value.startOffsetLeft = audioDotEle.value!.offsetLeft; position.value.startX = event.clientX; position.value.maxLeft = position.value.startOffsetLeft; position.value.maxRight = pgsWrapperEle.value!.offsetWidth - position.value.startOffsetLeft; } } event.preventDefault(); event.stopPropagation(); }; /** * @description 鼠标移动 audioPlayer */ const mousemoveProgressHandle = (event: MouseEvent) => { if (dragFlag.value) { const clientX = event.clientX; let x = clientX - position.value.startX; if (x > position.value.maxRight) x = position.value.maxRight; if (x < -position.value.maxLeft) x = -position.value.maxLeft; const pgsWidth = pgsWrapperEle.value?.getBoundingClientRect().width; const reat = (position.value.startOffsetLeft + x) / pgsWidth!; audioEle.value!.currentTime = audioEle.value!.duration * reat; updateProgress(); } }; /** * @description 鼠标取消点击 */ const mouseupProgressHandle = () => dragFlag.value = false; onMounted(() => { if (startSongDragDot.value) { audioPlayer.value = document.querySelector('.audio-player'); audioDotEle.value = document.querySelector('.progress-dot'); // 在捕获中去触发点击 dot 事件. fix: 点击原点 offset 回到原点 bug audioDotEle.value?.addEventListener('mousedown', mousedownProgressHandle, true); audioPlayer.value?.addEventListener('mousemove', mousemoveProgressHandle, false); document.addEventListener('mouseup', mouseupProgressHandle, false); } }); onBeforeUnmount(() => { if (startSongDragDot.value) { audioPlayer.value?.removeEventListener('mousedown', mousedownProgressHandle); audioPlayer.value?.removeEventListener('mousemove', mousemoveProgressHandle); document.removeEventListener('mouseup', mouseupProgressHandle); } }); };
Atas ialah kandungan terperinci Ajar anda langkah demi langkah cara menulis pemain menggunakan Vue3. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!