基本完成歌曲详情
This commit is contained in:
@@ -1,42 +1,105 @@
|
||||
<script setup>
|
||||
import { ref, onUnmounted, watch } from "vue";
|
||||
import { ref, onUnmounted, watch, toRaw, nextTick } from "vue";
|
||||
import { NButton, NIcon } from "naive-ui";
|
||||
import { useStore } from "vuex";
|
||||
import svgChevrongDown from "@/assets/svgs/ChevronDown.svg";
|
||||
import pubsub from "pubsub-js";
|
||||
import ArtistsSpan from "@/components/ArtistsSpan.vue";
|
||||
import AlbumSpan from "@/components/AlbumSpan.vue";
|
||||
import _ from 'lodash';
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const songInfo = ref(null);
|
||||
const song = ref(null);
|
||||
const lyric = ref(null);
|
||||
const lyArr = ref([]);
|
||||
const coverAngle = ref(0);
|
||||
const currTime = ref(0);
|
||||
const totalTime = ref(0);
|
||||
const currentLyricLine = ref(false);
|
||||
const currentLyricIdx = ref(-1);
|
||||
const lyList = ref('')
|
||||
|
||||
let interval;
|
||||
//#region 唱机
|
||||
let interval = [];
|
||||
watch(
|
||||
() => store.state.settings.playing,
|
||||
(val) => {
|
||||
if(val){
|
||||
interval = setInterval(() => {
|
||||
coverAngle.value += .5
|
||||
}, 100);
|
||||
() => [store.state.settings.playing, store.state.showSongDetail],
|
||||
([playing, showSongDetail]) => {
|
||||
if (playing && showSongDetail) {
|
||||
interval.push(
|
||||
setInterval(() => {
|
||||
coverAngle.value += 0.5;
|
||||
}, 40)
|
||||
);
|
||||
} else {
|
||||
clearInterval(interval)
|
||||
interval.map((item) => clearInterval(item));
|
||||
interval = [];
|
||||
}
|
||||
|
||||
},
|
||||
{immediate: true}
|
||||
{ immediate: true }
|
||||
);
|
||||
//#endregion
|
||||
|
||||
//#region 歌词
|
||||
|
||||
//处理歌词
|
||||
const handleLyric = (ly) => {
|
||||
lyArr.value = [];
|
||||
const lines = ly.split("\n");
|
||||
const re = /^\[(\d+):(\d+(.\d+)?)\](.*)$/;
|
||||
lines.forEach((line) => {
|
||||
// console.log(line);
|
||||
// let match = re.exec(line)
|
||||
// console.log(match);
|
||||
// console.log(Number(line.replace(re,'$1')))
|
||||
if (re.test(line))
|
||||
lyArr.value.push({
|
||||
time:
|
||||
Number(line.replace(re, "$1")) * 60 * 1000 +
|
||||
Number(line.replace(re, "$2")) * 1000,
|
||||
lyric: line.replace(re, "$4"),
|
||||
origin: line,
|
||||
});
|
||||
});
|
||||
// lyList.value.scrollTop = 0;
|
||||
// console.log(lyArr.value);
|
||||
};
|
||||
|
||||
watch(
|
||||
()=> currentLyricIdx.value,
|
||||
(val)=>{
|
||||
if(val>0){
|
||||
// let elContent = document.getElementsByClassName('ly-content')[0]
|
||||
let el = document.getElementsByClassName('ly-key-lines')[val]
|
||||
lyList.value.scrollTop = el.offsetTop - 100
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
)
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 处理消息订阅
|
||||
|
||||
const token = pubsub.subscribe("zp", (msg, data) => {
|
||||
switch (msg) {
|
||||
case "zp.songInfo":
|
||||
console.log("SongDetail: 收到歌曲详细信息。", data);
|
||||
songInfo.value = data;
|
||||
// console.log("SongDetail: 收到歌曲详细信息。", data);
|
||||
song.value = data;
|
||||
break;
|
||||
case "zp.lyric":
|
||||
lyric.value = data;
|
||||
handleLyric(data);
|
||||
break;
|
||||
case "zp.progress":
|
||||
totalTime.value = data.total * 1000;
|
||||
currTime.value = data.progress * 1000;
|
||||
currentLyricIdx.value = _.findLastIndex(lyArr.value,(item) => {
|
||||
return item.time < currTime.value;
|
||||
});
|
||||
// console.log(currentLyricIdx.value);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -61,8 +124,9 @@ onUnmounted(() => {
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
<div id="sdContent" v-if="songInfo">
|
||||
<div id="sdContent" v-if="song">
|
||||
<div class="detail">
|
||||
<!-- 唱机 -->
|
||||
<div class="disk">
|
||||
<div class="styli">
|
||||
<img
|
||||
@@ -74,20 +138,57 @@ onUnmounted(() => {
|
||||
<img class="disk" src="@/assets/images/disk.png" />
|
||||
<img
|
||||
class="cover"
|
||||
:src="songInfo.album.picUrl"
|
||||
:src="song.album.picUrl"
|
||||
:style="{ transform: 'rotateZ(' + coverAngle + 'deg)' }"
|
||||
/>
|
||||
</div>
|
||||
<div class="pic"></div>
|
||||
</div>
|
||||
<div class="song">
|
||||
歌曲
|
||||
<div class="name"></div>
|
||||
<div class="others"></div>
|
||||
<div class="ly"></div>
|
||||
<div class="name">{{ song.name }}</div>
|
||||
<div class="alias">
|
||||
{{ song.alias.length > 0 ? song.alias.join(" ") : "" }}
|
||||
</div>
|
||||
<div class="others">
|
||||
<div class="album">
|
||||
专辑:
|
||||
<AlbumSpan
|
||||
:album="song.album"
|
||||
:onLeave="
|
||||
() => {
|
||||
pubsub.publish('zp.toggleSongDetail');
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="artists">
|
||||
歌手:
|
||||
<ArtistsSpan
|
||||
:artists="song.artists"
|
||||
:onLeave="
|
||||
() => {
|
||||
pubsub.publish('zp.toggleSongDetail');
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ly" v-if="lyric" ref="lyList">
|
||||
<div class="ly-content" >
|
||||
<div
|
||||
class="ly-line"
|
||||
v-for="(line, idx) in lyArr"
|
||||
key="idx"
|
||||
:class="{ current: currentLyricIdx == idx, ['ly-key-lines']: true, }"
|
||||
>
|
||||
{{ line.lyric }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ly-right"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comments"></div>
|
||||
</div>
|
||||
<div class="comments"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -115,6 +216,7 @@ export default {};
|
||||
right: 0;
|
||||
bottom: 64px;
|
||||
background-color: #f6f6f6;
|
||||
overflow-y: auto;
|
||||
|
||||
.styli {
|
||||
position: relative;
|
||||
@@ -138,7 +240,7 @@ export default {};
|
||||
height: 50px;
|
||||
}
|
||||
.disk {
|
||||
--back-color: #eee;
|
||||
--back-color: #ddd;
|
||||
--width-num: 340;
|
||||
--padding-num: 10;
|
||||
--width: calc(var(--width-num) * 1px);
|
||||
@@ -170,7 +272,57 @@ export default {};
|
||||
}
|
||||
.song {
|
||||
position: relative;
|
||||
width: 400px;
|
||||
width: 330px;
|
||||
margin-left: 30px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
.name {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.others {
|
||||
// display: flex;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
.album {
|
||||
flex: 1;
|
||||
}
|
||||
.artists {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.ly {
|
||||
position: relative;
|
||||
margin-top: 15px;
|
||||
height: 290px;
|
||||
overflow-y: auto;
|
||||
|
||||
// background-image : linear-gradient(180deg,hsla(255,0%,100%,0),rgba(255, 255, 255, 0.521));
|
||||
|
||||
.ly-content {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin-bottom: 100px;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// justify-items: center;
|
||||
|
||||
.ly-line {
|
||||
min-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.current {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user