完成ktv歌词功能
parent
8992e316d0
commit
bae28fac35
File diff suppressed because one or more lines are too long
|
@ -223,11 +223,10 @@ table {overflow:auto;display:table;width:100%;line-height:2.5rem;
|
||||||
|
|
||||||
section {flex:1;display:flex;
|
section {flex:1;display:flex;
|
||||||
|
|
||||||
&.left {justify-content:flex-start;
|
&.left {justify-content:flex-start;}
|
||||||
|
|
||||||
span {background: linear-gradient(to right, #ff0 25%, #fff 25%);;background-clip:text;color:transparent;}
|
|
||||||
}
|
|
||||||
&.right {justify-content:flex-end}
|
&.right {justify-content:flex-end}
|
||||||
|
|
||||||
|
span {background-clip:text!important;color:transparent;}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,10 +124,10 @@
|
||||||
|
|
||||||
<div class="lrc-box">
|
<div class="lrc-box">
|
||||||
<section class="left">
|
<section class="left">
|
||||||
<span>我有句话悄悄想对你说</span>
|
<span :text="lrc.l.txt" :css="{background: lrc.l.bg}"></span>
|
||||||
</section>
|
</section>
|
||||||
<section class="right">
|
<section class="right">
|
||||||
<span>想着你成为我一种坏习惯</span>
|
<span :text="lrc.r.txt" :css="{background: lrc.r.bg}"></span>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
27
js/app.js
27
js/app.js
|
@ -8,6 +8,7 @@ import '/lib/anot.next.js'
|
||||||
import layer from '/lib/layer/index.js'
|
import layer from '/lib/layer/index.js'
|
||||||
import store from '/lib/store/index.js'
|
import store from '/lib/store/index.js'
|
||||||
import AudioPlayer from '/lib/audio/index.js'
|
import AudioPlayer from '/lib/audio/index.js'
|
||||||
|
import Lyrics from '/lib/lyrics/index.js'
|
||||||
|
|
||||||
import Api from '/js/api.js'
|
import Api from '/js/api.js'
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ window.LS = store.collection('local')
|
||||||
window.TS = store.collection('temp')
|
window.TS = store.collection('temp')
|
||||||
// 音乐播放器
|
// 音乐播放器
|
||||||
window.SONIST = new AudioPlayer()
|
window.SONIST = new AudioPlayer()
|
||||||
|
window.LYRICS = new Lyrics()
|
||||||
|
|
||||||
let appInit = fs.cat(APP_INI_PATH)
|
let appInit = fs.cat(APP_INI_PATH)
|
||||||
|
|
||||||
|
@ -80,6 +82,11 @@ Anot({
|
||||||
album: '',
|
album: '',
|
||||||
time: 0,
|
time: 0,
|
||||||
duration: 0
|
duration: 0
|
||||||
|
},
|
||||||
|
ctrlLrc: '暂无歌词...',
|
||||||
|
lrc: {
|
||||||
|
l: { bg: '', txt: '' },
|
||||||
|
r: { bg: '', txt: '' }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
skip: [],
|
skip: [],
|
||||||
|
@ -136,6 +143,7 @@ Anot({
|
||||||
let pp = (ax - 124) / (aw - 124)
|
let pp = (ax - 124) / (aw - 124)
|
||||||
this.curr.time = pp * this.curr.duration
|
this.curr.time = pp * this.curr.duration
|
||||||
SONIST.seek(this.curr.time)
|
SONIST.seek(this.curr.time)
|
||||||
|
LYRICS.seek(this.curr.time)
|
||||||
if (!this.isPlaying) {
|
if (!this.isPlaying) {
|
||||||
this.draw()
|
this.draw()
|
||||||
}
|
}
|
||||||
|
@ -150,12 +158,23 @@ Anot({
|
||||||
|
|
||||||
SONIST.on('play', time => {
|
SONIST.on('play', time => {
|
||||||
this.curr.time = time
|
this.curr.time = time
|
||||||
|
LYRICS.update(time)
|
||||||
})
|
})
|
||||||
|
|
||||||
SONIST.on('end', time => {
|
SONIST.on('end', time => {
|
||||||
this.nextSong(1)
|
this.nextSong(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 控制条的单行歌词
|
||||||
|
LYRICS.on('ctrl-lrc', lrc => {
|
||||||
|
this.ctrlLrc = lrc
|
||||||
|
})
|
||||||
|
|
||||||
|
// ktv模式的歌词
|
||||||
|
LYRICS.on('ktv-lrc', lrc => {
|
||||||
|
this.lrc = lrc
|
||||||
|
})
|
||||||
|
|
||||||
this.activeModule(this.mod)
|
this.activeModule(this.mod)
|
||||||
|
|
||||||
remote.app.on('browser-window-focus', _ => {
|
remote.app.on('browser-window-focus', _ => {
|
||||||
|
@ -239,6 +258,7 @@ Anot({
|
||||||
let wl = this.__HEIGHT__ + 180 // 文字的坐标X
|
let wl = this.__HEIGHT__ + 180 // 文字的坐标X
|
||||||
|
|
||||||
let { time, duration, title, artist } = this.curr
|
let { time, duration, title, artist } = this.curr
|
||||||
|
let lrc = this.ctrlLrc
|
||||||
let pp = time / duration // 进度百分比
|
let pp = time / duration // 进度百分比
|
||||||
time = Anot.filters.time(time)
|
time = Anot.filters.time(time)
|
||||||
duration = Anot.filters.time(duration)
|
duration = Anot.filters.time(duration)
|
||||||
|
@ -282,7 +302,7 @@ Anot({
|
||||||
// 歌词
|
// 歌词
|
||||||
this.__CTX__.fillStyle = COLORS[this.ktvMode].lrc
|
this.__CTX__.fillStyle = COLORS[this.ktvMode].lrc
|
||||||
this.__CTX__.font = '48px' + FONTS_NAME
|
this.__CTX__.font = '48px' + FONTS_NAME
|
||||||
this.__CTX__.fillText(`暂无歌词...`, wl, 180)
|
this.__CTX__.fillText(lrc, wl, 180)
|
||||||
|
|
||||||
// 进度条
|
// 进度条
|
||||||
this.__CTX__.fillStyle = COLORS[this.ktvMode].bar1
|
this.__CTX__.fillStyle = COLORS[this.ktvMode].bar1
|
||||||
|
@ -361,9 +381,11 @@ Anot({
|
||||||
// 此时仅更新播放控制条的信息即可
|
// 此时仅更新播放控制条的信息即可
|
||||||
if (song) {
|
if (song) {
|
||||||
song.time = 0
|
song.time = 0
|
||||||
|
this.ctrlLrc = '暂无歌词...'
|
||||||
this.updateCurr(song)
|
this.updateCurr(song)
|
||||||
this.isPlaying = true
|
this.isPlaying = true
|
||||||
this.draw(true)
|
this.draw(true)
|
||||||
|
LYRICS.__init__(song.lyrics)
|
||||||
} else {
|
} else {
|
||||||
if (SONIST.stat === 'ready') {
|
if (SONIST.stat === 'ready') {
|
||||||
let played = this.isPlaying
|
let played = this.isPlaying
|
||||||
|
@ -379,9 +401,12 @@ Anot({
|
||||||
let lastPlay = Anot.ls('last-play') || 0
|
let lastPlay = Anot.ls('last-play') || 0
|
||||||
SONIST.play(lastPlay).then(it => {
|
SONIST.play(lastPlay).then(it => {
|
||||||
it.time = 0
|
it.time = 0
|
||||||
|
this.ctrlLrc = '暂无歌词...'
|
||||||
this.updateCurr(it)
|
this.updateCurr(it)
|
||||||
this.draw(true)
|
this.draw(true)
|
||||||
// this.ktvMode = 1
|
// this.ktvMode = 1
|
||||||
|
|
||||||
|
LYRICS.__init__(it.lyrics)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/**
|
||||||
|
* 歌词模块
|
||||||
|
* @author yutent<yutent@doui.cc>
|
||||||
|
* @date 2019/01/04 16:25:25
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const log = console.log
|
||||||
|
const fs = require('iofs')
|
||||||
|
const { EventEmitter } = require('events')
|
||||||
|
const util = require('util')
|
||||||
|
|
||||||
|
class Lyrics {
|
||||||
|
__init__(lrcFile) {
|
||||||
|
this.lib = []
|
||||||
|
this.curr = []
|
||||||
|
this.lrc = {
|
||||||
|
l: { bg: '', txt: '' },
|
||||||
|
r: { bg: '', txt: '' }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lrcFile || !fs.exists(lrcFile)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let lrc = fs
|
||||||
|
.cat(lrcFile)
|
||||||
|
.toString('utf8')
|
||||||
|
.split('\n')
|
||||||
|
|
||||||
|
this.lib = lrc
|
||||||
|
.map(it => {
|
||||||
|
if (it) {
|
||||||
|
let matches = it.match(/^\[([0-9\.\:]+)\](.+)/)
|
||||||
|
let time = matches[1]
|
||||||
|
let txt = matches[2]
|
||||||
|
time = time.split(/[:\.]/).map(t => +t)
|
||||||
|
let start = time[0] * 60 + time[1] + time[2] / 100
|
||||||
|
return { start, txt }
|
||||||
|
}
|
||||||
|
return
|
||||||
|
})
|
||||||
|
.filter(it => it)
|
||||||
|
|
||||||
|
for (let i = 0, it; (it = this.lib[i++]); ) {
|
||||||
|
if (this.lib[i]) {
|
||||||
|
it.duration = +(this.lib[i].start - it.start).toFixed(2)
|
||||||
|
it.end = this.lib[i].start
|
||||||
|
} else {
|
||||||
|
it.duration = 3
|
||||||
|
it.end = it.start + 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.tmpLib = this.lib.concat()
|
||||||
|
|
||||||
|
return this.lib.length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
seek(time) {
|
||||||
|
this.tmpLib = []
|
||||||
|
for (let it of this.lib) {
|
||||||
|
if (it.start > time) {
|
||||||
|
this.tmpLib.push(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update(time) {
|
||||||
|
if (!this.curr.length && this.tmpLib.length) {
|
||||||
|
this.curr = this.tmpLib.splice(0, 2)
|
||||||
|
}
|
||||||
|
let stat = 0
|
||||||
|
|
||||||
|
// 当前时间小于第1句的结束时间
|
||||||
|
if (time <= this.curr[0].end) {
|
||||||
|
// 如果第2句比第1句的时间要小,需要补新
|
||||||
|
if (this.curr[1].start < this.curr[0].start && time > this.curr[1].end) {
|
||||||
|
if (this.tmpLib.length) {
|
||||||
|
this.curr[1] = this.tmpLib.shift()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (time < this.curr[1].end) {
|
||||||
|
// 如果第1句比第2句的时间要小,需要补新
|
||||||
|
if (this.curr[0].start < this.curr[1].start) {
|
||||||
|
if (this.tmpLib.length) {
|
||||||
|
this.curr[0] = this.tmpLib.shift()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.tmpLib.length) {
|
||||||
|
this.curr = this.tmpLib.splice(0, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stat = (this.curr[0].start < this.curr[1].start) ^ 1
|
||||||
|
|
||||||
|
this.lrc.l.txt = this.curr[0].txt
|
||||||
|
this.lrc.r.txt = this.curr[1].txt
|
||||||
|
|
||||||
|
if (stat === 0) {
|
||||||
|
let pp = (
|
||||||
|
((time - this.curr[0].start) / this.curr[0].duration) *
|
||||||
|
100
|
||||||
|
).toFixed(2)
|
||||||
|
this.lrc.l.bg = `linear-gradient(to right, #ff5061 ${pp}%, #fff ${pp}%)`
|
||||||
|
this.lrc.r.bg = '#fff'
|
||||||
|
this.emit('ctrl-lrc', this.lrc.l.txt)
|
||||||
|
} else {
|
||||||
|
let pp = (
|
||||||
|
((time - this.curr[1].start) / this.curr[1].duration) *
|
||||||
|
100
|
||||||
|
).toFixed(2)
|
||||||
|
this.lrc.l.bg = '#fff'
|
||||||
|
this.lrc.r.bg = `linear-gradient(to right, #ff5061 ${pp}%, #fff ${pp}%)`
|
||||||
|
this.emit('ctrl-lrc', this.lrc.r.txt)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emit('ktv-lrc', this.lrc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(Lyrics, EventEmitter)
|
||||||
|
|
||||||
|
export default Lyrics
|
Reference in New Issue