You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
288 lines
10 KiB
288 lines
10 KiB
<template>
|
|
<ele-card header="音乐播放功能演示">
|
|
<div class="demo-music-wrap">
|
|
<div class="music-wrapper">
|
|
<div
|
|
:key="current.vid"
|
|
class="music-body"
|
|
:style="{ backgroundImage: `url('${current.poster}')` }"
|
|
>
|
|
<div ref="lrcRef" class="lrc-wrap" style="height: 100%"></div>
|
|
<canvas ref="analyzeRef" class="analyze-wrap"></canvas>
|
|
</div>
|
|
<div class="music-footer">
|
|
<div class="music-controls">
|
|
<el-icon>
|
|
<step-backward-filled @click="playPrev" />
|
|
</el-icon>
|
|
<el-icon @click="playOrPause">
|
|
<pause-filled v-if="playing" style="transform: scale(1.4)" />
|
|
<play-filled v-else style="transform: scale(1.4)" />
|
|
</el-icon>
|
|
<el-icon>
|
|
<step-forward-filled @click="playNext" />
|
|
</el-icon>
|
|
</div>
|
|
<ele-xg-player
|
|
:key="current.vid"
|
|
:config="config"
|
|
@player="onPlayer"
|
|
style="flex: 1; overflow: visible"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</ele-card>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref } from 'vue';
|
|
import type Player from 'xgplayer';
|
|
import MusicPreset, { Analyze, Lyric } from 'xgplayer-music';
|
|
import {
|
|
PlayFilled,
|
|
PauseFilled,
|
|
StepForwardFilled,
|
|
StepBackwardFilled
|
|
} from '@/components/icons';
|
|
/** 歌词 */
|
|
const lyrics = [
|
|
{
|
|
vid: '000001',
|
|
lrc: `[00:00.00] 脆弱一分钟\n[00:00.00] 作曲 : 林家谦\n[00:00.00] 作词 : 徐世珍/吴辉福\n[00:00.000]编曲:林家谦\n[00:00.000]时钟不要走\n[00:04.220]让我脆弱一分钟\n[00:07.440]要多久才能习惯被放手\n[00:15.800]马克杯空了 暖暖的温热\n[00:22.660]却还在我手中停留\n[00:27.960]\n[00:29.790]勇气不要走\n[00:32.200]给我理由再冲动\n[00:35.690]去相信爱情 就算还在痛\n[00:43.960]如果我不说不会有人懂\n[00:50.720]失去你我有多寂寞\n[00:55.610]还是愿意\n[00:57.580]付出一切仅仅为了一个好梦\n[01:03.980]梦里有人真心爱我 陪我快乐也陪我沉默\n[01:11.260]没有无缘无故的痛承受越多越成熟\n[01:18.630]能让你拥抱更好的我\n[01:25.030] 谁也不要走\n[01:28.270]应该是一种奢求\n[01:31.900]可是我只想 握紧你的手\n[01:39.780]我宁愿等候 也不愿错过\n[01:46.630]你对我微笑的时候\n[01:56.780]\n[02:18.910]还是愿意\n[02:21.320]用尽全力仅仅为了一个以后\n[02:27.870]哪怕生命并不温柔哪怕被幸福一再反驳\n[02:34.870]也要相信伤痕累累 其实只是在琢磨\n[02:42.070]能让你为之一亮 的我\n[02:53.910]\n[02:56.350]制作人:林宥嘉\n[02:57.750]制作助理:张婕汝\n[02:59.010]录音师:陈文骏、叶育轩\n[03:00.410]录音室:白金录音室\n[03:01.740]混音师:SimonLi @ nOiz\n[03:03.000]OP: Terence Lam Production & Co. (Warner/Chappell Music, HK Ltd.)\n[03:04.050]SP: Warner/Chappell Music Taiwan Ltd.\n[03:04.910]OP:Universal Ms Publ Ltd Taiwan\n`
|
|
},
|
|
{
|
|
vid: '000002',
|
|
lrc: `[00:00.000]Westlife-My Love\n[00:08.800]An empty street\n[00:10.510]An empty house\n[00:12.200]A hole inside my heart\n[00:15.470]I am all alone\n[00:17.270]The rooms are getting smaller\n[00:22.440]I wonder how\n[00:23.850]I wonder why\n[00:25.460]I wonder where they are\n[00:28.870]The days we had\n[00:30.500]The songs we sang together\n[00:33.320]Oh yeah\n[00:35.480]And oh my love\n[00:38.710]I am holding on forever\n[00:42.200]Reaching for a love that seems so far\n[00:48.070]So i say a little prayer\n[00:51.100]And hope my dreams will take me there\n[00:54.520]Where the skies are blue to see you once again, my love\n[01:01.230]Over seas and coast to coast\n[01:04.430]To find a place i love the most\n[01:07.830]Where the fields are green to see you once again, my love\n[01:18.730]I try to read\n[01:20.210]I go to work\n[01:21.900]I am laughing with my friends\n[01:25.180]But i cannot stop to keep myself from thinking\n[01:29.710]Oh no I wonder how\n[01:33.420]I wonder why\n[01:34.960]I wonder where they are\n[01:38.470]The days we had\n[01:40.150]The songs we sang together\n[01:42.900]Oh yeah And oh my love\n[01:48.300]I am holding on forever\n[01:51.760]Reaching for a love that seems so far Mark:\n[01:58.070]So i say a little prayer\n[02:01.400]And hope my dreams will take me there\n[02:04.800]Where the skies are blue to see you once again, my love\n[02:11.400]Over seas and coast to coast\n[02:14.720]To find a place i love the most\n[02:18.080]Where the fields are green to see you once again, my love\n[02:24.040]To hold you in my arms\n[02:27.290]To promise you my love\n[02:30.610]To tell you from the heart\n[02:33.870]You are all i am thinking of\n[02:45.460]I am reaching for a love that seems so far\n[02:51.940]So i say a little prayer\n[02:54.820]And hope my dreams will take me there\n[02:58.080]Where the skies are blue to see you once again, my love\n[03:04.700]Over seas and coast to coast\n[03:07.980]To find a place i love the most\n[03:11.520]Where the fields are green to see you once again,my love\n[03:19.000]Where the fields are green to see you once again,my love\n[03:31.580]Over seas and coast to coast\n[03:34.670]To find a place i love the most\n[03:38.110]Where the fields are green to see you once again,my love\n[03:19.020]say a little prayer\n[03:22.300]dreams will take me there\n[03:24.770]Where the skies are blue to see you once again\n`
|
|
}
|
|
];
|
|
/** 歌曲 */
|
|
const songs = [
|
|
{
|
|
vid: '000001',
|
|
src: '//sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/music/audio.mp3',
|
|
poster:
|
|
'https://imgcache.qq.com/open_proj/proj_qcloud_v2/gateway/solution/general-video/css/img/scene/1.png'
|
|
},
|
|
{
|
|
vid: '000002',
|
|
src: '//sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/music/audio-en.mp3',
|
|
poster:
|
|
'https://imgcache.qq.com/open_proj/proj_qcloud_v2/gateway/solution/general-video/css/img/scene/6.png'
|
|
}
|
|
];
|
|
|
|
/** 播放器配置 */
|
|
const config = ref({
|
|
url: songs[0].src,
|
|
volume: 1,
|
|
height: 54,
|
|
width: '100%',
|
|
autoplay: false,
|
|
mediaType: 'audio',
|
|
marginControls: true,
|
|
controls: { initShow: true, mode: 'flex' },
|
|
ignores: [
|
|
'play',
|
|
'mobile',
|
|
'playbackrate',
|
|
'musicbackward',
|
|
'musicforward',
|
|
'musiccover',
|
|
'musicmeta',
|
|
'musicnext',
|
|
'musicprev'
|
|
],
|
|
presets: ['default', MusicPreset],
|
|
videoConfig: { crossOrigin: 'anonymous' }
|
|
});
|
|
|
|
/** 频谱容器 */
|
|
const analyzeRef = ref<HTMLCanvasElement | null>(null);
|
|
|
|
/** 歌词容器 */
|
|
const lrcRef = ref<HTMLDivElement | null>(null);
|
|
|
|
/** 当前歌曲 */
|
|
const current = ref(songs[0]);
|
|
|
|
/** 是否播放状态 */
|
|
const playing = ref(false);
|
|
|
|
interface Sate {
|
|
player: Player | null;
|
|
analyze: Analyze | null;
|
|
}
|
|
|
|
const state: Sate = {
|
|
/** 视频播放器实例 */
|
|
player: null,
|
|
/** 频谱实例 */
|
|
analyze: null
|
|
};
|
|
|
|
/** 播放器渲染完成 */
|
|
const onPlayer = (ins: Player) => {
|
|
state.player = ins;
|
|
state.player.crossOrigin = 'anonymous';
|
|
state.player.on('pause', () => {
|
|
playing.value = false;
|
|
});
|
|
state.player.on('ended', () => {
|
|
playing.value = false;
|
|
playNext();
|
|
});
|
|
state.player.on('play', () => {
|
|
playing.value = true;
|
|
// 初始化频谱
|
|
if (!state.analyze && analyzeRef.value) {
|
|
state.analyze = new Analyze(state.player, analyzeRef.value, {
|
|
stroke: 1,
|
|
mode: 'vertLines',
|
|
bgColor: 'rgba(0, 0, 0, 0)'
|
|
});
|
|
}
|
|
});
|
|
// 初始化歌词
|
|
const lyric = new Lyric(
|
|
[lyrics.find((d) => d.vid == current.value.vid)?.lrc],
|
|
lrcRef.value
|
|
);
|
|
lyric.bind(state.player);
|
|
lyric.show();
|
|
};
|
|
|
|
/** 播放/暂停 */
|
|
const playOrPause = () => {
|
|
if (state.player) {
|
|
if (state.player.paused) {
|
|
state.player.play();
|
|
} else {
|
|
state.player.pause();
|
|
}
|
|
}
|
|
};
|
|
|
|
/** 播放下一曲 */
|
|
const playNext = () => {
|
|
const index = songs.findIndex((d) => d.vid === current.value.vid);
|
|
if (index === songs.length - 1) {
|
|
current.value = songs[0];
|
|
} else {
|
|
current.value = songs[index + 1];
|
|
}
|
|
if (state.analyze) {
|
|
state.analyze.stop();
|
|
state.analyze = null;
|
|
}
|
|
config.value = { ...config.value, url: current.value.src, autoplay: true };
|
|
};
|
|
|
|
/** 播放上一曲 */
|
|
const playPrev = () => {
|
|
const index = songs.findIndex((d) => d.vid === current.value.vid);
|
|
if (index === 0) {
|
|
current.value = songs[songs.length - 1];
|
|
} else {
|
|
current.value = songs[index - 1];
|
|
}
|
|
if (state.analyze) {
|
|
state.analyze.stop();
|
|
state.analyze = null;
|
|
}
|
|
config.value = { ...config.value, url: current.value.src, autoplay: true };
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.music-body {
|
|
height: 325px;
|
|
position: relative;
|
|
background-color: #000;
|
|
background-repeat: no-repeat;
|
|
background-size: cover;
|
|
|
|
&::before,
|
|
&::after {
|
|
content: '';
|
|
height: 80px;
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
background-image: linear-gradient(
|
|
to bottom,
|
|
rgba(0, 0, 0, 0.6),
|
|
rgba(0, 0, 0, 0)
|
|
);
|
|
z-index: 2;
|
|
}
|
|
|
|
&::after {
|
|
top: auto;
|
|
bottom: 0;
|
|
background-image: linear-gradient(
|
|
to bottom,
|
|
rgba(0, 0, 0, 0),
|
|
rgba(0, 0, 0, 0.6)
|
|
);
|
|
}
|
|
}
|
|
|
|
.lrc-wrap :deep(.xgplayer-lrcWrap) {
|
|
height: 100%;
|
|
padding: 80px 0;
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
text-align: center;
|
|
color: rgba(255, 255, 255, 0.8);
|
|
font-size: 16px;
|
|
line-height: 2;
|
|
overflow: auto;
|
|
scrollbar-width: none;
|
|
|
|
.xgplayer-lyric-item-active {
|
|
color: #e31106;
|
|
font-weight: bold;
|
|
}
|
|
|
|
&::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
.analyze-wrap {
|
|
width: 100%;
|
|
height: 60px;
|
|
display: block;
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
z-index: 3;
|
|
}
|
|
|
|
.music-footer {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
background: #000;
|
|
color: #fff;
|
|
|
|
:deep(.xg-center-grid) {
|
|
padding-left: 0;
|
|
}
|
|
}
|
|
|
|
.music-controls {
|
|
font-size: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.el-icon {
|
|
cursor: pointer;
|
|
margin-left: 16px;
|
|
}
|
|
}
|
|
</style>
|
|
|