console
let video = document.querySelector('video');
let track = video.addTextTrack('subtitles', 'text', 'zh-cn');
let timer = null;
track.mode = 'showing';
let lyric = `
[00:00.88]不该
[00:05.54]词:方文山
[00:06.12]曲:周杰伦
[00:08.62]演唱:周杰伦,aMEI
[00:10.29]
[00:24.31]Jay:
[00:25.91]
[00:26.67]假装我们还在一块
[00:30.83]
[00:33.16]我真的演不出来
[00:36.31]
[00:39.46]还是不习惯你不在
[00:43.97]
[00:44.89]这身份转变太快
[00:48.43]
[00:49.64]aMEI:
[00:50.73]
[00:51.89]画面里不需要旁白
[00:57.12]
[00:58.64]却谁都看的出来
[01:02.74]
[01:05.02]是我情绪涌了上来
[01:09.97]
[01:10.64]想哭却一遍空白
[01:14.29]
[01:15.52]Jay:
[01:16.90]雪地里相爱
[01:18.13]他们说零下已结晶的誓言不会坏
[01:22.47]合:
[01:23.25]但爱的状态
[01:24.53]却不会永远都冰封
[01:26.93]而透明的存在
[01:28.84]合:
[01:29.20]轻轻飘 落下来
[01:32.19]许下的梦 融化的太快
[01:35.05]
[01:36.01]或许我们都不该醒来
[01:39.79]
[01:40.71]aMEI:
[01:41.46]你还是住在我的回忆里不出来
[01:47.55]Jay:
[01:48.07]让我们微笑离开让故事留下来
[01:53.75]合:
[01:54.26]放手后爱依然在
[01:57.41]雪融了就应该花开
[02:01.86]缘若尽了
[02:03.47]就不该再重来
[02:06.64]aMEI:
[02:07.19]你依旧住在我的回忆里不出来
[02:13.07]Jay:
[02:13.52]我离开将你的手交给下个最爱
[02:19.25]aMEI:
[02:19.85]纠缠与
[02:20.80]合:
[02:21.14]固执等待
[02:23.00]反而是另一种伤害
[02:26.83]
[02:27.34]彼此紧握的手松开
[02:30.88]去拥抱更多未来
[02:34.69]
[02:45.95]Jay:
[02:47.15]错过的时间怎么买
[02:51.57]
[02:53.91]谁都付不出来
[02:57.30]
[02:57.86]aMEI:
[02:59.34]
[03:00.18]或许我们学会释怀
[03:04.37]
[03:05.71]让过去安静下来
[03:09.13]
[03:11.07]合:
[03:12.24]雪地里相爱
[03:13.34]他们说零下已结晶的誓言不会坏
[03:17.44]
[03:18.53]但爱的状态
[03:19.79]却不会永远都冰封
[03:22.12]而透明的存在
[03:23.91]合:
[03:24.43]轻轻飘 落下来
[03:27.45]许下的梦融化的太快
[03:30.31]
[03:31.09]或许我们都不该醒来
[03:34.79]
[03:36.28]aMEI:
[03:36.80]你还是住在我的回忆里不出来
[03:42.73]Jay:
[03:43.22]让我们微笑离开让故事留下来
[03:49.03]合:
[03:49.51]放手后爱依然在
[03:52.57]雪融了就应该花开
[03:56.32]
[03:56.98]缘若尽了
[03:58.57]就不该再重来
[04:01.83]aMEI:
[04:02.34]你依旧住在我的回忆里不出来
[04:08.28]Jay:
[04:08.73]我离开将你的手交给下个
[04:12.67]合:
[04:13.16]最爱
[04:15.09]aMEI:
[04:15.54]纠缠与
[04:16.10]合:
[04:16.45]固执等待
[04:18.27]反而是另一种伤害
[04:22.67]彼此紧握的手松开
[04:26.21]去拥抱更多未来
[04:30.00]
`
let titles = (function () {
let reg = /(?:\[(?<min>[0-9]+)\:(?<sec>[0-9]+\.[0-9]+)\])(?<text>.*)/;
let mreg = /(\[[0-9]+\:[0-9]+\.[0-9]+\].*)/g;
let arr = lyric.match(mreg) || [];
let lyrics = arr.filter(function (item) {
return reg.test(item);
}).map(function (item) {
let match = reg.exec(item);
let text = match.groups.text;
let sec = parseFloat(match.groups.sec);
let min = parseInt(match.groups.min);
let btime = parseFloat(sec + parseFloat((min * 60).toFixed(4)))+1;
return {
text,
btime
}
}).map(function (item, index, array) {
if (array[index + 1]) {
item.etime = array[index + 1].btime - 0.1;
} else {
item.etime = item.btime + 10;
}
return item;
})
return lyrics;
})();
function addTitles() {
titles.forEach(function (item) {
let cue = new VTTCue(item.btime, item.etime, item.text);
cue.line = 10;
track.addCue(cue);
});
}
video.onloadedmetadata = addTitles;
function replaceRule(targetIndex, option) {
if (document.styleSheets[0].cssRules[targetIndex]) {
document.styleSheets[0].removeRule(targetIndex);
}
document.styleSheets[0].addRule(option.selector, option.style, targetIndex);
}
function animate(begin, end) {
let duration = end - begin;
timer = setInterval(function () {
let step = (100-((end - video.currentTime) / (end-begin) * 100)).toFixed(4);
replaceRule(1,{
selector: 'video.video::cue',
style: `background-size: ${step}%;`,
});
if(video.currentTime > end) {
clearInterval(timer);
}
}, 20);
}
track.oncuechange = function (e) {
let ac = e.currentTarget.activeCues[0]
if (ac) {
animate(ac.startTime, ac.endTime);
}
}
video.onseeking = function () {
clearInterval(timer);
}
video.onpause = function () {
clearInterval(timer);
}
video.onplay = function () {
clearInterval(timer);
let ac = track.activeCues[0];
if(ac) {
animate(ac.startTime,ac.endTime);
}
}
video.onratechange = function () {
clearInterval(timer);
let ac = track.activeCues[0];
if(ac) {
animate(ac.startTime,ac.endTime);
}
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=, initial-scale=">
<meta http-equiv="X-UA-Compatible" content="">
<title></title>
</head>
<body>
<video class="video" height="500" data-size="50% 100%" controls src="https://mvwebfs.ali.kugou.com/202205081703/a5824e188afde871638eabcdd4dea4cf/G059/M02/16/17/ew0DAFdiZ1iARGOeCQrmQ1joFRw667.mp4"></video>
</body>
</html>
.video::cue {
background: linear-gradient(to right,#2cdd71,#2cdd71) #eee no-repeat;
-webkit-background-clip: text;
color: transparent;
transform: scale(2);
font-weight: 600;
}