<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.self_progress {
background-image: linear-gradient(to right, #00d09b, #00dfc4);
transition: all 0.3s;
}
.lyrics {
overflow-y: scroll;
text-align: center;
line-height: 25px;
font-size: 14px;
}
::-webkit-scrollbar {
display: none;
}
.text {
position: relative;
white-space: nowrap;
overflow: hidden;
width: 100%;
color: transparent;
background: linear-gradient(to right, #00dfc4, #0098a6);
background-clip: text;
animation: fill-lyrics linear forwards;
}
@keyframes fill-lyrics {
0% {
background-size: 0 100%;
}
100% {
background-size: 100% 100%;
}
}
</style>
</head>
<body>
<div id="app" class="h-100vh w-100vw grid place-items-center">
<div class="shadow h-80px w-800px py-10px flex flex-col px-15px">
<audio
@timeupdate="change('updateProgress')"
ref="audioPlayer"
:src="musicSrc"
></audio>
<div class="flex items-center h-50px">
<img
src="https://image.qwq.link/images/2023/12/15/twitter_1-19agabiran__20231203-112256_1731272804455375216_photo.jpg"
alt=""
class="object-cover h-full w-50px rounded-3px"
/>
<div class="flex-1 h-full lyrics">
<div
ref="lyrics"
:class="{'text' : item.words == currentIndex}"
v-for="item in lyrics"
:key="item.time"
:style="{ animationDuration: 1 + 's' }"
>
{{item.words}}
</div>
</div>
<img
@click="change('status')"
class="cursor-pointer ml-auto"
:src="isStart ? './stop.svg' : './start.svg'"
alt=""
/>
</div>
<div class="mt-auto">
<div
class="w-full h-3px bg-#efefef rounded-full"
@click="change('settingPosition',$event)"
>
<div
class="self_progress h-full"
:style="{width: progress + '%'}"
></div>
</div>
</div>
</div>
</div>
<script src="./vue/unocss.js"></script>
<script src="./vue/vue.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
musicSrc: './我怎么能猜透你-承桓.mp3',
progress: 0,
isStart: false,
currentIndex: '',
lyrics: [],
};
},
methods: {
change(type, event) {
const Fn = {
play: () => {
this.$refs.audioPlayer.play();
},
pause: () => {
this.$refs.audioPlayer.pause();
},
status: () => {
this.isStart = !this.isStart;
if (this.isStart) this.change('play');
else this.change('pause');
},
updateProgress: () => {
const audio = this.$refs.audioPlayer;
const progress = (audio.currentTime / audio.duration) * 100;
this.progress = progress.toFixed(2);
for (var i = 0; i < this.lyrics.length; i++) {
if (audio.currentTime < this.lyrics[i].time) {
this.currentIndex = this.lyrics[i - 1].words;
let dom = this.$refs.lyrics[i];
dom.scrollIntoView({
behavior: 'smooth',
block: 'end',
inline: 'end',
});
return i - 1;
} else {
this.currentIndex = this.lyrics[i].words;
}
}
},
settingPosition: () => {
const progressBar = event.target;
const rect = progressBar.getBoundingClientRect();
const position = (event.clientX - rect.left) / rect.width;
const audio = this.$refs.audioPlayer;
audio.currentTime = position * audio.duration;
},
};
Fn[type]();
},
formatTime(time) {
var parts = time.split(':');
return Number(parts[0] * 60) + Number(parts[1]);
},
},
created() {
this.lyrics = [
{
time: '00:00.0',
words: '我怎么能猜透你-承桓',
},
{
time: '00:00.07',
words: '词:小兔',
},
{
time: '00:00.15',
words: '曲:李云宵',
},
{
time: '00:00.23',
words: '编曲:楠哈哈',
},
{
time: '00:00.31',
words: '制作人:一寸光年团队',
},
{
time: '00:00.39',
words: '混音:张鸣利/承桓',
},
{
time: '00:00.46',
words: '和声:承桓',
},
{
time: '00:00.54',
words: '企划:葵Aria',
},
{
time: '00:00.62',
words: '制作公司&OP:一寸光年',
},
{
time: '00:00.7',
words: '【未经著作权人许可不得翻唱翻录或使用】',
},
{
time: '00:00.78',
words: '我咋能猜透你嘞',
},
{
time: '00:03.21',
words: '你又不是真心嘞',
},
{
time: '00:05.07',
words: '早知道后劲那么冲',
},
{
time: '00:06.96',
words: '还不如做朋友',
},
{
time: '00:08.76',
words: '我咋能赢老你嘞',
},
{
time: '00:10.68',
words: '是我先认真哩',
},
{
time: '00:12.6',
words: '为什么走着走着',
},
{
time: '00:14.94',
words: '只剩影子和我',
},
{
time: '00:18.15',
words: '遇见你跟他一起走',
},
{
time: '00:20.19',
words: '希望你说他是朋友',
},
{
time: '00:22.14',
words: '结果缺我都懒得缺',
},
{
time: '00:24.0',
words: '说句分手就走',
},
{
time: '00:25.68',
words: '那你说嫩老些漂亮话',
},
{
time: '00:27.54',
words: '说想跟我有以后',
},
{
time: '00:29.34',
words: '想开我就难受',
},
{
time: '00:31.05',
words: '不爱我你说这咋了某',
},
{
time: '00:33.09',
words: '我把我真心给老你',
},
{
time: '00:35.01',
words: '你让我栽跟头',
},
{
time: '00:36.93',
words: '不舍了说你了坏话',
},
{
time: '00:38.85',
words: '只能用酒浇愁',
},
{
time: '00:40.68',
words: '你往我心里钉钉子',
},
{
time: '00:42.51',
words: '凿我的心里直疼',
},
{
time: '00:44.4',
words: '就不争气 就还想着你',
},
{
time: '00:47.61',
words: '我咋能猜透你嘞',
},
{
time: '00:49.8',
words: '你又不是真心嘞',
},
{
time: '00:51.87',
words: '早知道后劲那么冲',
},
{
time: '00:53.85',
words: '还不如做朋友',
},
{
time: '00:55.65',
words: '我咋能赢老你嘞',
},
{
time: '00:57.51',
words: '是我先认真哩',
},
{
time: '00:59.43',
words: '为什么走着走着',
},
{
time: '01:01.71',
words: '只剩影子和我',
},
{
time: '01:06.39',
words: '主动了太久太累了',
},
{
time: '01:08.79',
words: '在乎久了会崩溃',
},
{
time: '01:10.68',
words: '你走的那天流眼泪',
},
{
time: '01:12.54',
words: '从鼻子流到嘴里头',
},
{
time: '01:14.61',
words: '你是真有手段',
},
{
time: '01:16.26',
words: '随意拿爱去摆置俺',
},
{
time: '01:18.39',
words: '俺还傻了不清',
},
{
time: '01:19.74',
words: '想为你挡下每颗子弹',
},
{
time: '01:21.99',
words: '你让我难过的事儿',
},
{
time: '01:23.79',
words: '我放在心里嚼',
},
{
time: '01:25.8',
words: '嚼到烂嚼到透',
},
{
time: '01:27.57',
words: '嚼到第二天清早切',
},
{
time: '01:29.61',
words: '既然没想跟我走到底',
},
{
time: '01:31.770004',
words: '嫩为啥要骗我',
},
{
time: '01:33.42',
words: '让我对你付出嫩老些',
},
{
time: '01:36.42',
words: '我咋能猜透你嘞',
},
{
time: '01:38.79',
words: '你又不是真心嘞',
},
{
time: '01:40.65',
words: '早知道后劲那么冲',
},
{
time: '01:42.6',
words: '还不如做朋友',
},
{
time: '01:44.4',
words: '我咋能赢老你嘞',
},
{
time: '01:46.380005',
words: '是我先认真哩',
},
{
time: '01:48.15',
words: '为什么走着走着',
},
{
time: '01:50.490005',
words: '只剩影子和我',
},
{
time: '02:06.51',
words: '我咋能猜透你嘞',
},
{
time: '02:08.76',
words: '你又不是真心嘞',
},
{
time: '02:10.65',
words: '早知道后劲那么冲',
},
{
time: '02:12.57',
words: '还不如做朋友',
},
{
time: '02:14.37',
words: '我咋能赢老你嘞',
},
{
time: '02:16.26',
words: '是我先认真哩',
},
{
time: '02:18.15',
words: '为什么走着走着',
},
{
time: '02:20.45999',
words: '只剩影子和我',
},
];
this.lyrics = this.lyrics.map((e) => {
return {
time: this.formatTime(e.time),
words: e.words,
};
});
},
});
</script>
</body>
</html>