APlayer内部组件ts改造

This commit is contained in:
2023-01-25 02:00:10 +08:00
parent 34b92fbd1a
commit b49bebf654
15 changed files with 688 additions and 849 deletions
+102 -138
View File
@@ -15,150 +15,114 @@
</div>
</template>
<script>
import {parseLrc} from '../utils'
<script lang="ts" setup>
import { computed, watch, ref } from 'vue'
import { parseLrc } from '../utils'
import { MusicPlayerItem, StatType } from '@/model/api/music'
export default {
props: {
currentMusic: {
type: Object,
required: true
},
playStat: {
type: Object,
required: true
}
},
data () {
return {
displayLrc: '',
currentLineIndex: 0,
}
},
computed: {
lrcLines () {
return parseLrc(this.displayLrc)
},
currentLine () {
if (this.currentLineIndex > this.lrcLines.length - 1) {
return null
}
return this.lrcLines[this.currentLineIndex]
},
transformStyle () {
// transform: translateY(0); -webkit-transform: translateY(0);
return {
transform: `translateY(${-this.currentLineIndex * 16}px)`,
webkitTransform: `translateY(${-this.currentLineIndex * 16}px)`,
}
},
},
methods: {
applyLrc (lrc) {
if (/^https?:\/\//.test(lrc)) {
this.fetchLrc(lrc)
} else {
this.displayLrc = lrc
}
},
fetchLrc (src) {
fetch(src)
.then(response => response.text())
.then((lrc) => {
this.displayLrc = lrc
})
},
hideLrc () {
this.displayLrc = ''
},
},
watch: {
currentMusic: {
immediate: true,
handler (music) {
this.currentLineIndex = 0
if (music.lrc) {
this.applyLrc(music.lrc)
} else {
this.hideLrc()
}
}
},
'playStat.playedTime' (playedTime) {
for (let i = 0; i < this.lrcLines.length; i++) {
const line = this.lrcLines[i]
const nextLine = this.lrcLines[i + 1]
if (playedTime >= line[0] && (!nextLine || playedTime < nextLine[0])) {
this.currentLineIndex = i
}
}
},
const props = defineProps<{
currentMusic: MusicPlayerItem,
playStat: StatType
}>()
const displayLrc = ref('')
const currentLineIndex = ref(0)
const lrcLines = computed(() => parseLrc(displayLrc.value))
const transformStyle = computed(() => {
return {
transform: `translateY(${-currentLineIndex.value * 16}px)`,
webkitTransform: `translateY(${-currentLineIndex.value * 16}px)`,
}
})
const applyLrc = (lrc: string) => {
if (/^https?:\/\//.test(lrc)) {
fetch(lrc)
.then(response => response.text())
.then((lrc) => displayLrc.value = lrc)
} else {
displayLrc.value = lrc
}
}
watch(props.currentMusic, (music: MusicPlayerItem) => {
currentLineIndex.value = 0
if (music.lrc) {
applyLrc(music.lrc)
} else {
displayLrc.value = ''
}
}, { immediate: true })
watch(() => props.playStat.playedTime, (playedTime: number) => {
for (let i = 0; i < lrcLines.value.length; i++) {
const line = lrcLines.value[i]
const nextLine = lrcLines.value[i + 1]
if (playedTime >= line[0] && (!nextLine || playedTime < nextLine[0])) {
currentLineIndex.value = i
}
}
})
</script>
<style lang="less" scoped>
@import "../less/variables";
.aplayer-lrc {
position: relative;
height: @lrc-height;
text-align: center;
@import "../less/variables";
.aplayer-lrc {
position: relative;
height: @lrc-height;
text-align: center;
overflow: hidden;
margin-bottom: 7px;
&:before {
position: absolute;
top: 0;
z-index: 1;
display: block;
overflow: hidden;
margin-bottom: 7px;
&:before {
position: absolute;
top: 0;
z-index: 1;
display: block;
overflow: hidden;
width: 100%;
height: 10%;
content: ' ';
background: -moz-linear-gradient(top, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -webkit-linear-gradient(top, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#00ffffff', GradientType=0);
}
&:after {
position: absolute;
bottom: 0;
z-index: 1;
display: block;
overflow: hidden;
width: 100%;
height: 33%;
content: ' ';
background: -moz-linear-gradient(top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%);
background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%);
background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffffff', endColorstr='#ccffffff', GradientType=0);
}
p {
font-size: 12px;
color: #666;
line-height: 16px;
height: 16px;
padding: 0;
margin: 0;
transition: all 0.5s ease-out;
opacity: 0.4;
overflow: hidden;
&.aplayer-lrc-current {
opacity: 1;
overflow: visible;
height: initial;
}
}
.aplayer-lrc-contents {
width: 100%;
transition: all 0.5s ease-out;
user-select: text;
cursor: default;
width: 100%;
height: 10%;
content: ' ';
background: -moz-linear-gradient(top, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -webkit-linear-gradient(top, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#00ffffff', GradientType=0);
}
&:after {
position: absolute;
bottom: 0;
z-index: 1;
display: block;
overflow: hidden;
width: 100%;
height: 33%;
content: ' ';
background: -moz-linear-gradient(top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%);
background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%);
background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.8) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffffff', endColorstr='#ccffffff', GradientType=0);
}
p {
font-size: 12px;
color: #666;
line-height: 16px;
height: 16px;
padding: 0;
margin: 0;
transition: all 0.5s ease-out;
opacity: 0.4;
overflow: hidden;
&.aplayer-lrc-current {
opacity: 1;
overflow: visible;
height: initial;
}
}
.aplayer-lrc-contents {
width: 100%;
transition: all 0.5s ease-out;
user-select: text;
cursor: default;
}
}
</style>