逐字样式 BUG 修复

This commit is contained in:
NanoRocky 2025-01-14 03:12:44 +08:00
parent 8965a31838
commit f87f105e7c
4 changed files with 305 additions and 316 deletions

View File

@ -38,7 +38,7 @@
"@vicons/tabler": "^0.12.0",
"@vicons/utils": "^0.1.4",
"@vitejs/plugin-vue": "^5.2.1",
"eslint": "^9.17.0",
"eslint": "^9.18.0",
"eslint-plugin-vue": "^9.32.0",
"prettier": "^3.4.2",
"sass": "^1.83.1",
@ -57,4 +57,4 @@
"workbox-build": "^7.3.0"
}
}
}
}

115
pnpm-lock.yaml generated
View File

@ -82,11 +82,11 @@ importers:
specifier: ^5.2.1
version: 5.2.1(vite@6.0.7(jiti@2.4.1)(sass@1.83.1)(terser@5.37.0))(vue@3.5.13(typescript@5.6.3))
eslint:
specifier: ^9.17.0
version: 9.17.0(jiti@2.4.1)
specifier: ^9.18.0
version: 9.18.0(jiti@2.4.1)
eslint-plugin-vue:
specifier: ^9.32.0
version: 9.32.0(eslint@9.17.0(jiti@2.4.1))
version: 9.32.0(eslint@9.18.0(jiti@2.4.1))
prettier:
specifier: ^3.4.2
version: 3.4.2
@ -453,8 +453,8 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/plugin-transform-nullish-coalescing-operator@7.26.5':
resolution: {integrity: sha512-OHqczNm4NTQlW1ghrVY43FPoiRzbmzNVbcgVnMKZN/RQYezHUSdjACjaX50CD3B7UIAjv39+MlsrVDb3v741FA==}
'@babel/plugin-transform-nullish-coalescing-operator@7.26.6':
resolution: {integrity: sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
@ -600,8 +600,8 @@ packages:
resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==}
engines: {node: '>=6.9.0'}
'@babel/standalone@7.26.5':
resolution: {integrity: sha512-vXbSrFq1WauHvOg/XWcjkF6r7wDSHbN3+3Aro6LYjfODpGw8dCyqqbUMRX5LXlgzVAUrTSN6JkepFiHhLKHV5Q==}
'@babel/standalone@7.26.6':
resolution: {integrity: sha512-h1mkoNFYCqDkS+vTLGzsQYvp1v1qbuugk4lOtb/oyjArZ+EtreAaxcSYg3rSIzWZRQOjx4iqGe7A8NRYIMSTTw==}
engines: {node: '>=6.9.0'}
'@babel/template@7.25.9':
@ -796,16 +796,12 @@ packages:
resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/core@0.9.1':
resolution: {integrity: sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/eslintrc@3.2.0':
resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/js@9.17.0':
resolution: {integrity: sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==}
'@eslint/js@9.18.0':
resolution: {integrity: sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/object-schema@2.1.5':
@ -1418,8 +1414,8 @@ packages:
confbox@0.1.8:
resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
consola@3.3.3:
resolution: {integrity: sha512-Qil5KwghMzlqd51UXM0b6fyaGHtOC22scxrwrz4A2882LyUMwQjnvaedN1HAeXzphspQ6CpHkzMAWxBTUruDLg==}
consola@3.4.0:
resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==}
engines: {node: ^14.18.0 || >=16.10.0}
convert-source-map@2.0.0:
@ -1595,8 +1591,8 @@ packages:
resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
eslint@9.17.0:
resolution: {integrity: sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==}
eslint@9.18.0:
resolution: {integrity: sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
peerDependencies:
@ -2176,8 +2172,8 @@ packages:
engines: {node: '>=10'}
hasBin: true
mlly@1.7.3:
resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==}
mlly@1.7.4:
resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@ -2283,6 +2279,9 @@ packages:
pathe@1.1.2:
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
pathe@2.0.1:
resolution: {integrity: sha512-6jpjMpOth5S9ITVu5clZ7NOgHNsv5vRQdheL9ztp2vZmM6fRbLvyua1tiBIL4lk8SAe3ARzeXEly6siXCjDHDw==}
perfect-debounce@1.0.0:
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
@ -2366,9 +2365,9 @@ packages:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
readdirp@4.0.2:
resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
engines: {node: '>= 14.16.0'}
readdirp@4.1.1:
resolution: {integrity: sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==}
engines: {node: '>= 14.18.0'}
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
@ -3346,7 +3345,7 @@ snapshots:
'@babel/core': 7.26.0
'@babel/helper-plugin-utils': 7.26.5
'@babel/plugin-transform-nullish-coalescing-operator@7.26.5(@babel/core@7.26.0)':
'@babel/plugin-transform-nullish-coalescing-operator@7.26.6(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
'@babel/helper-plugin-utils': 7.26.5
@ -3523,7 +3522,7 @@ snapshots:
'@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-nullish-coalescing-operator': 7.26.5(@babel/core@7.26.0)
'@babel/plugin-transform-nullish-coalescing-operator': 7.26.6(@babel/core@7.26.0)
'@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.0)
@ -3565,7 +3564,7 @@ snapshots:
dependencies:
regenerator-runtime: 0.14.1
'@babel/standalone@7.26.5':
'@babel/standalone@7.26.6':
optional: true
'@babel/template@7.25.9':
@ -3674,9 +3673,9 @@ snapshots:
'@esbuild/win32-x64@0.24.2':
optional: true
'@eslint-community/eslint-utils@4.4.1(eslint@9.17.0(jiti@2.4.1))':
'@eslint-community/eslint-utils@4.4.1(eslint@9.18.0(jiti@2.4.1))':
dependencies:
eslint: 9.17.0(jiti@2.4.1)
eslint: 9.18.0(jiti@2.4.1)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
@ -3693,10 +3692,6 @@ snapshots:
dependencies:
'@types/json-schema': 7.0.15
'@eslint/core@0.9.1':
dependencies:
'@types/json-schema': 7.0.15
'@eslint/eslintrc@3.2.0':
dependencies:
ajv: 6.12.6
@ -3711,7 +3706,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@eslint/js@9.17.0': {}
'@eslint/js@9.18.0': {}
'@eslint/object-schema@2.1.5': {}
@ -3786,7 +3781,7 @@ snapshots:
dependencies:
'@nuxt/schema': 3.14.1592(rollup@2.79.2)
c12: 2.0.1
consola: 3.3.3
consola: 3.4.0
defu: 6.1.4
destr: 2.0.3
globby: 14.0.2
@ -3795,7 +3790,7 @@ snapshots:
jiti: 2.4.1
klona: 2.0.6
knitwork: 1.2.0
mlly: 1.7.3
mlly: 1.7.4
pathe: 1.1.2
pkg-types: 1.3.0
scule: 1.3.0
@ -3814,7 +3809,7 @@ snapshots:
dependencies:
c12: 2.0.1
compatx: 0.1.8
consola: 3.3.3
consola: 3.4.0
defu: 6.1.4
hookable: 5.5.3
pathe: 1.1.2
@ -4294,7 +4289,7 @@ snapshots:
dotenv: 16.4.7
giget: 1.2.3
jiti: 2.4.1
mlly: 1.7.3
mlly: 1.7.4
ohash: 1.1.4
pathe: 1.1.2
perfect-debounce: 1.0.0
@ -4342,14 +4337,14 @@ snapshots:
chokidar@4.0.3:
dependencies:
readdirp: 4.0.2
readdirp: 4.1.1
chownr@2.0.0:
optional: true
citty@0.1.6:
dependencies:
consola: 3.3.3
consola: 3.4.0
optional: true
color-convert@2.0.1:
@ -4373,7 +4368,7 @@ snapshots:
confbox@0.1.8: {}
consola@3.3.3:
consola@3.4.0:
optional: true
convert-source-map@2.0.0: {}
@ -4602,16 +4597,16 @@ snapshots:
escape-string-regexp@5.0.0: {}
eslint-plugin-vue@9.32.0(eslint@9.17.0(jiti@2.4.1)):
eslint-plugin-vue@9.32.0(eslint@9.18.0(jiti@2.4.1)):
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0(jiti@2.4.1))
eslint: 9.17.0(jiti@2.4.1)
'@eslint-community/eslint-utils': 4.4.1(eslint@9.18.0(jiti@2.4.1))
eslint: 9.18.0(jiti@2.4.1)
globals: 13.24.0
natural-compare: 1.4.0
nth-check: 2.1.1
postcss-selector-parser: 6.1.2
semver: 7.6.3
vue-eslint-parser: 9.4.3(eslint@9.17.0(jiti@2.4.1))
vue-eslint-parser: 9.4.3(eslint@9.18.0(jiti@2.4.1))
xml-name-validator: 4.0.0
transitivePeerDependencies:
- supports-color
@ -4630,14 +4625,14 @@ snapshots:
eslint-visitor-keys@4.2.0: {}
eslint@9.17.0(jiti@2.4.1):
eslint@9.18.0(jiti@2.4.1):
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0(jiti@2.4.1))
'@eslint-community/eslint-utils': 4.4.1(eslint@9.18.0(jiti@2.4.1))
'@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.19.1
'@eslint/core': 0.9.1
'@eslint/core': 0.10.0
'@eslint/eslintrc': 3.2.0
'@eslint/js': 9.17.0
'@eslint/js': 9.18.0
'@eslint/plugin-kit': 0.2.5
'@humanfs/node': 0.16.6
'@humanwhocodes/module-importer': 1.0.1
@ -4842,7 +4837,7 @@ snapshots:
giget@1.2.3:
dependencies:
citty: 0.1.6
consola: 3.3.3
consola: 3.4.0
defu: 6.1.4
node-fetch-native: 1.6.4
nypm: 0.3.12
@ -5132,7 +5127,7 @@ snapshots:
local-pkg@0.5.1:
dependencies:
mlly: 1.7.3
mlly: 1.7.4
pkg-types: 1.3.0
locate-path@6.0.0:
@ -5225,10 +5220,10 @@ snapshots:
mkdirp@1.0.4:
optional: true
mlly@1.7.3:
mlly@1.7.4:
dependencies:
acorn: 8.14.0
pathe: 1.1.2
pathe: 2.0.1
pkg-types: 1.3.0
ufo: 1.5.4
@ -5262,7 +5257,7 @@ snapshots:
nypm@0.3.12:
dependencies:
citty: 0.1.6
consola: 3.3.3
consola: 3.4.0
execa: 8.0.1
pathe: 1.1.2
pkg-types: 1.3.0
@ -5336,6 +5331,8 @@ snapshots:
pathe@1.1.2: {}
pathe@2.0.1: {}
perfect-debounce@1.0.0:
optional: true
@ -5363,7 +5360,7 @@ snapshots:
pkg-types@1.3.0:
dependencies:
confbox: 0.1.8
mlly: 1.7.3
mlly: 1.7.4
pathe: 1.1.2
possible-typed-array-names@1.0.0: {}
@ -5409,7 +5406,7 @@ snapshots:
dependencies:
picomatch: 2.3.1
readdirp@4.0.2: {}
readdirp@4.1.1: {}
reflect.getprototypeof@1.0.10:
dependencies:
@ -5820,7 +5817,7 @@ snapshots:
fast-glob: 3.3.3
local-pkg: 0.5.1
magic-string: 0.30.17
mlly: 1.7.3
mlly: 1.7.4
pathe: 1.1.2
picomatch: 4.0.2
pkg-types: 1.3.0
@ -5861,7 +5858,7 @@ snapshots:
local-pkg: 0.5.1
magic-string: 0.30.17
minimatch: 9.0.5
mlly: 1.7.3
mlly: 1.7.4
unplugin: 1.16.1
vue: 3.5.13(typescript@5.6.3)
optionalDependencies:
@ -5884,7 +5881,7 @@ snapshots:
untyped@1.5.2:
dependencies:
'@babel/core': 7.26.0
'@babel/standalone': 7.26.5
'@babel/standalone': 7.26.6
'@babel/types': 7.26.5
citty: 0.1.6
defu: 6.1.4
@ -5943,10 +5940,10 @@ snapshots:
dependencies:
vue: 3.5.13(typescript@5.6.3)
vue-eslint-parser@9.4.3(eslint@9.17.0(jiti@2.4.1)):
vue-eslint-parser@9.4.3(eslint@9.18.0(jiti@2.4.1)):
dependencies:
debug: 4.4.0
eslint: 9.17.0(jiti@2.4.1)
eslint: 9.18.0(jiti@2.4.1)
eslint-scope: 7.2.2
eslint-visitor-keys: 3.4.3
espree: 9.6.1

View File

@ -51,27 +51,21 @@
<paw />
</Icon> -->
<span class="yrc-box">
<span class="yrc-2 lrc-text text-hidden" id="yrc-2-wrap">
<span v-for="i in store.playerLrc" :key="`lrc-over-char-${i[2]}-${i[3]}`" v-html="i[4]">
<span class="yrc-2 lrc-text text-hidden" id="yrc-2-wrap">
<span v-for="i in store.playerLrc" :key="`lrc-over-char-${i[2]}-${i[3]}`" v-html="i[4]">
</span>
</span>
</span>
<span class="yrc-1 lrc-text text-hidden" id="yrc-1-wrap">
<span v-for="i in store.playerLrc" :key="`lrc-char-${i[2]}-${i[3]}`" :class="[
'yrc-char',
i[0] && Number(i[6]) > 0 ? 'fade-in' : 'fade-in-start',
i[0] && Number(i[5]) > 1019 && Number(i[6]) > 0 ? 'long-tone' : 'fade-in-start',
i[0] && Number(i[6]) <= 0 ? 'fade-out' : '',
i[1] ? 'yrc-style-s2' : 'yrc-style-s1'
]" :id="`lrc-char-${i[2]}-${i[3]}`" v-html="i[4]">
<span class="yrc-1 lrc-text text-hidden" id="yrc-1-wrap">
<span v-for="i in store.playerLrc" :key="`lrc-char-${i[2]}-${i[3]}`" :class="[
'yrc-char',
i[0] && Number(i[6]) > 0 ? 'fade-in' : 'fade-in-start',
i[0] && Number(i[5]) > 1019 && Number(i[6]) > 0 ? 'long-tone' : 'fade-in-start',
i[0] && Number(i[6]) <= 0 ? 'fade-out' : '',
i[1] ? 'yrc-style-s2' : 'yrc-style-s1'
]" :id="`lrc-char-${i[2]}-${i[3]}`" v-html="i[4]">
</span>
</span>
</span>
<!-- <span class="yrc-2 lrc-text text-hidden" id="yrc-2-wrap">
<span v-for="i in store.playerLrc" :key="`lrc-over-char-${i[2]}-${i[3]}`" v-html="i[4]" />
</span>
<span class="yrc-1 lrc-text text-hidden" id="yrc-1-wrap">
<span v-for="i in store.playerLrc" :key="`lrc-char-${i[2]}-${i[3]}`" v-html="i[4]" />
</span> -->
</span>
<!-- <Icon size="20" style="transform: rotate(18deg);" class="paws-2">
<paw />
</Icon> -->
@ -102,18 +96,17 @@
<script setup>
import { MusicOne } from "@icon-park/vue-next";
// import { Icon } from "@vicons/utils";
// import { Paw } from "@vicons/ionicons5";
import { Icon } from "@vicons/utils";
import { Paw } from "@vicons/ionicons5";
import { mainStore } from "@/store";
import config from "@/../package.json";
import { ref, watch, computed, onMounted, nextTick, onUpdated } from "vue";
const store = mainStore();
const fullYear = new Date().getFullYear();
// const lrcContainer = ref(null);
// const scrollPosition = ref(0);
// const currentLine = ref(0);
const lrcContainer = ref(null);
const scrollPosition = ref(0);
const currentLine = ref(0);
const showProgressIcon = ref(false);
const handleMouseEnter = () => {
@ -200,17 +193,15 @@ const progressBarWidth = computed(() => {
});
// yrc part
watch(() => store.getPlayerLrc, (_new,_old) => {
const isLineByLine = !store.yrcEnable || store.yrcTemp.length == 0 || store.yrcLoading
watch(() => store.getPlayerLrc, (_new, _old) => {
const isLineByLine = !store.yrcEnable || store.yrcTemp.length == 0 || store.yrcLoading;
if (!store.playerYrcShowPro || isLineByLine) {
return
return;
};
// const now = player.value.audioStatus.playedTime * 1000;
const audio = document.querySelector('audio')
const audio = document.querySelector('audio');
if (audio == undefined) {
return
}
return;
};
const now = audio.currentTime * 1000;
const yrc2 = document.getElementsByClassName("yrc-box")[0];
if (yrc2 == undefined) {
@ -221,16 +212,12 @@ watch(() => store.getPlayerLrc, (_new,_old) => {
if (inputDom.length == 0 || outputDom.length == 0) {
return;
};
// console.log(store.yrcTemp[0][0])
const yrcFiltered = store.yrcTemp.filter((i) => i[0] < now && now < i[0] + i[1]);
const yrcFiltered = store.yrcTemp.filter((i) => i[0] < now && now < i[0] + i[1]);
if (yrcFiltered.length == 0) {
// console.log('h')
return;
};
const nowLine = yrcFiltered[yrcFiltered.length - 1][2]
// console.log(nowLine)
const nowLine = yrcFiltered[yrcFiltered.length - 1][2];
for (let i = 0; i < nowLine.length; i++) {
// console.log(JSON.stringify(nowLine[i]))
const [[start, duration], _a, _b, _c] = nowLine[i];
const inputItem = inputDom[i];
if (!inputItem || inputItem.hasAttribute('data-start')) {
@ -249,7 +236,7 @@ watch(() => store.getPlayerLrc, (_new,_old) => {
fill: "forwards",
easing: "linear",
};
outputItem.style.transform = "translateY(-1px)"
outputItem.style.transform = "translateY(-1px)";
const outputAnimate = outputItem.animate(
[
{ width: 0 },
@ -257,16 +244,24 @@ watch(() => store.getPlayerLrc, (_new,_old) => {
],
animateOptions,
);
// animationTmp.push(outputAnimate);
outputAnimate.onfinish = () => {
outputItem.style.transform = "translateY(1px)";
// animationTmp = animationTmp.filter(a => a !== outputAnimate);
outputItem.animate(
[
{ transform: "translateY(-1px)" },
{ transform: "translateY(1px)" },
],
{
duration: 300,
fill: "forwards",
easing: "linear",
}
);
};
inputItem.setAttribute("data-start",true)
inputItem.setAttribute("data-start", true);
};
})
});
// setInterval(yrcPro, 50);
</script>
<style lang="scss" scoped>
@ -403,6 +398,11 @@ watch(() => store.getPlayerLrc, (_new,_old) => {
white-space: nowrap;
overflow: hidden;
width: 0;
transition:
opacity 0.3s linear,
color 0.5s linear,
transform 0.3s linear,
width 0.3s linear;
}
#yrc-2-wrap {

View File

@ -1,24 +1,8 @@
<template>
<APlayer
v-if="playList[0]"
ref="player"
:audio="playList"
:autoplay="store.playerAutoplay"
:theme="theme"
:autoSwitch="false"
:loop="store.playerLoop"
:order="store.playerOrder"
:volume="volume"
:showLrc="true"
:listFolded="listFolded"
:listMaxHeight="listMaxHeight"
:noticeSwitch="false"
@play="onPlay"
@pause="onPause"
@timeupdate="onTimeUp"
@error="loadMusicError"
@loadstart="onLoadStart"
/>
<APlayer v-if="playList[0]" ref="player" :audio="playList" :autoplay="store.playerAutoplay" :theme="theme"
:autoSwitch="false" :loop="store.playerLoop" :order="store.playerOrder" :volume="volume" :showLrc="true"
:listFolded="listFolded" :listMaxHeight="listMaxHeight" :noticeSwitch="false" @play="onPlay" @pause="onPause"
@Loadstart="onLoadStart" @timeupdate="onTimeUp" @error="loadMusicError" />
</template>
<script setup>
@ -112,7 +96,7 @@ onMounted(() => {
navigator.mediaSession.setActionHandler("previoustrack", () => {
changeSong(0); // 0
});
}
};
console.log("音乐加载完成");
});
} catch (err) {
@ -132,81 +116,10 @@ onMounted(() => {
const vstyle = import.meta.env.VITE_TTS_Style;
SpeechLocal("播放器加载失败.mp3");
}
}
};
});
});
const fetchYrc = async (yrcUrl) => {
const yrcSource = await fetch(yrcUrl);
const yrcText = await yrcSource.text();
store.yrcIndex = playIndex.value;
if (yrcText.startsWith("[ch:0]")) {
store.yrcEnable = true;
store.yrcTemp = decodeYrc(yrcText);
store.yrcLoading = false;
return;
} else if (!store.playerYrcATDB) {
store.yrcEnable = false;
store.yrcTemp = [];
store.yrcLoading = false;
return;
}
// AMLL TTML Database
const songUrlInf = new URLSearchParams(new URL(yrcUrl).search);
const songId = songUrlInf.get("id");
const songServer = songUrlInf.get("server");
if (!songId) {
return;
}
const songUrlInfUrl = store.playerYrcATDBF
? {
netease: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.yrc`,
tencent: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.qrc`,
}
: {
netease: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.yrc`,
tencent: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.qrc`,
};
if (!["netease", "tencent"].includes(songServer)) {
return;
}
try {
const amllUrl = songUrlInfUrl[songServer].replace("${songIdlrc}", songId);
const amllSource = await fetch(amllUrl);
const amllText = await amllSource.text();
} catch (e) {
console.log(e);
store.yrcEnable = true;
store.yrcTemp = decodeYrc(amllText);
store.yrcLoading = false;
}
};
function onLoadStart() {
try {
const aplayer = player.value.aplayer;
const lyrics = aplayer.lyrics[playIndex.value];
if (store.playerYrcShow != true) {
store.yrcEnable = false;
store.yrcTemp = [];
store.yrcLoading = false;
return;
}
if (store.yrcIndex == playIndex.value) {
return;
}
const yrcUrl = aplayer.audio[aplayer.index]["lrc"] + "&yrc=true";
store.yrcIndex = playIndex.value;
store.yrcLoading = true;
fetchYrc(yrcUrl);
} catch (error) {
store.yrcEnable = false;
store.yrcTemp = [];
store.yrcLoading = false;
console.error(error);
}
}
//
const onPlay = () => {
console.log("播放");
@ -237,7 +150,7 @@ const onPlay = () => {
},
],
});
}
};
if (store.webSpeech) {
if (store.playerSpeechName) {
@ -246,15 +159,15 @@ const onPlay = () => {
const vstyle = import.meta.env.VITE_TTS_Style;
Speech(
"正在播放,“" +
store.getPlayerData.artist +
"”的歌曲,《" +
store.getPlayerData.name +
"》。",
store.getPlayerData.artist +
"”的歌曲,《" +
store.getPlayerData.name +
"》。",
voice,
vstyle,
);
}
}
};
};
};
//
@ -262,102 +175,6 @@ const onPause = () => {
store.setPlayerState(player.value.audioRef.paused);
};
function doLrcSync(lrc) {
const playerLyricIndex = player.value.aplayer.lyricIndex;
const output = [[true, 1, playerLyricIndex, 0, lrc]];
if (store.playerLrc.toString() != output.toString()) {
store.setPlayerLrc(output);
return;
}
}
function syncLrc() {
//
const aplayer = player.value.aplayer;
// console.log(playIndex.value)
const lyrics = aplayer.lyrics[playIndex.value];
const playerLyricIndex = player.value.aplayer.lyricIndex;
if (lyrics === undefined || lyrics[playerLyricIndex] === undefined) {
return doLrcSync("歌词加载中...");
}
let lrc = lyrics[playerLyricIndex][1];
if (lrc === "Loading") {
return doLrcSync("歌词加载中...");
} else if (lrc === "Not available" && !store.playerYrcATDB) {
return doLrcSync("歌词加载失败");
} else if (lrc === "Not availible") {
//
const songUrlInfw = new URLSearchParams(new URL(yrcUrl).search);
const songIdlrc = songUrlInfw.get("id");
const songServerlrc = songUrlInfw.get("server");
if (!songIdlrc) {
return doLrcSync("歌词加载失败");
}
const songUrlInfwurl = store.playerYrcATDBF
? {
netease: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.lrc`,
tencent: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.lrc`,
}
: {
netease: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.lrc`,
tencent: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.lrc`,
};
if (!["netease", "tencent"].includes(songServerlrc)) {
return doLrcSync("歌词加载失败");
}
const amllUrllrc = songUrlInfwurl[songServerlrc].replace("${songIdlrc}", songIdlrc);
fetch(amllUrllrc)
.then((response) => response.text())
.catch(() => {
doLrcSync("歌词加载失败");
});
return doLrcSync("歌词加载中...");
}
doLrcSync(lrc);
}
function syncYrc() {
const now = player.value.audioStatus.playedTime * 1000;
const yrcFiltered = store.yrcTemp.filter((i) => i[0] < now);
const yrcLyric =
yrcFiltered.length > 0
? yrcFiltered.slice(-1)[0][2].map((it) => {
const [[start, duration], word, line, row] = it;
const isCurrent = now >= start && now <= start + duration;
const isSungLyrics = start + duration < now;
const lessdur = start + duration - now;
return [isCurrent, isSungLyrics, line, row, word, duration, lessdur, "auto"];
})
: [[true, 1, 0, 0, `${store.playerTitle} - ${store.playerArtist}`]];
if (store.playerLrc.toString() != yrcLyric.toString()) {
store.setPlayerLrc(yrcLyric);
}
}
//
const onTimeUp = () => {
store.playerCurrentTime = player.value.audioStatus.playedTime;
store.playerDuration = player.value.audioStatus.duration;
// YRC ...bushi... qrc yrc
showYrcRunning = 1;
try {
// try 西[20720,-4200]西 try
if (player.value == null) {
return;
}
const aplayer = player.value.aplayer;
// const isLineByLine = false;
const isLineByLine = !store.yrcEnable || store.yrcTemp.length == 0 || store.yrcLoading
if (isLineByLine) {
return syncLrc();
} else {
return syncYrc();
}
} catch (error) {
console.error(error);
}
};
//
const playToggle = () => {
player.value.toggle();
@ -391,7 +208,7 @@ const loadMusicError = () => {
const voice = import.meta.env.VITE_TTS_Voice;
const vstyle = import.meta.env.VITE_TTS_Style;
SpeechLocal("歌曲加载失败.mp3");
}
};
} else {
notice = "播放歌曲出现错误";
if (store.webSpeech) {
@ -399,8 +216,8 @@ const loadMusicError = () => {
const voice = import.meta.env.VITE_TTS_Voice;
const vstyle = import.meta.env.VITE_TTS_Style;
SpeechLocal("播放器未知异常.mp3");
}
}
};
};
ElMessage({
message: notice,
grouping: true,
@ -415,6 +232,185 @@ const loadMusicError = () => {
);
};
//
const fetchYrc = async (yrcUrl) => {
//
const yrcSource = await fetch(yrcUrl);
const yrcText = await yrcSource.text();
store.yrcIndex = playIndex.value;
if (yrcText.startsWith("[ch:0]")) {
store.yrcEnable = true;
store.yrcTemp = decodeYrc(yrcText);
store.yrcLoading = false;
return;
} else if (!store.playerYrcATDB) {
store.yrcEnable = false;
store.yrcTemp = [];
store.yrcLoading = false;
return;
};
// AMLL TTML Database
const songUrlInf = new URLSearchParams(new URL(yrcUrl).search);
const songId = songUrlInf.get("id");
const songServer = songUrlInf.get("server");
if (!songId) {
return;
};
const songUrlInfUrl = store.playerYrcATDBF
? {
netease: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.yrc`,
tencent: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.qrc`,
}
: {
netease: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.yrc`,
tencent: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.qrc`,
};
if (!["netease", "tencent"].includes(songServer)) {
return;
};
try {
const amllUrl = songUrlInfUrl[songServer].replace("${songIdlrc}", songId);
const amllSource = await fetch(amllUrl);
const amllText = await amllSource.text();
} catch (e) {
console.log(e);
store.yrcEnable = true;
store.yrcTemp = decodeYrc(amllText);
store.yrcLoading = false;
};
};
function onLoadStart() {
//
try {
if (player.value == null || player.value.aplayer == null) {
return;
};
const aplayer = player.value.aplayer;
const lyrics = aplayer.lyrics[playIndex.value];
if (store.playerYrcShow != true) {
store.yrcEnable = false;
store.yrcTemp = [];
store.yrcLoading = false;
return;
};
if (store.yrcIndex == playIndex.value) {
return;
};
const yrcUrl = aplayer.audio[aplayer.index]["lrc"] + "&yrc=true";
store.yrcIndex = playIndex.value;
store.yrcLoading = true;
fetchYrc(yrcUrl);
} catch (error) {
store.yrcEnable = false;
store.yrcTemp = [];
store.yrcLoading = false;
console.error(error);
};
};
function syncLrc() {
if (player.value == null || player.value.aplayer == null) {
return;
};
//
const aplayer = player.value.aplayer;
const lyrics = aplayer.lyrics[playIndex.value];
const playerLyricIndex = player.value.aplayer.lyricIndex;
if (lyrics === undefined || lyrics[playerLyricIndex] === undefined) {
return doLrcSync("歌词加载中...");
};
let lrc = lyrics[playerLyricIndex][1];
if (lrc === "Loading") {
return doLrcSync("歌词加载中...");
} else if (lrc === "Not available" && !store.playerYrcATDB) {
return doLrcSync("歌词加载失败");
} else if (lrc === "Not availible") {
//
const songUrlInfw = new URLSearchParams(new URL(yrcUrl).search);
const songIdlrc = songUrlInfw.get("id");
const songServerlrc = songUrlInfw.get("server");
if (!songIdlrc) {
return doLrcSync("歌词加载失败");
};
const songUrlInfwurl = store.playerYrcATDBF
? {
netease: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.lrc`,
tencent: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.lrc`,
}
: {
netease: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.lrc`,
tencent: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.lrc`,
};
if (!["netease", "tencent"].includes(songServerlrc)) {
return doLrcSync("歌词加载失败");
};
const amllUrllrc = songUrlInfwurl[songServerlrc].replace("${songIdlrc}", songIdlrc);
fetch(amllUrllrc)
.then((response) => response.text())
.catch(() => {
doLrcSync("歌词加载失败");
});
return doLrcSync("歌词加载中...");
};
doLrcSync(lrc);
};
const onTimeUp = () => {
store.playerCurrentTime = player.value.audioStatus.playedTime;
store.playerDuration = player.value.audioStatus.duration;
if (showYrcRunning == 0 && player.value != null && player.value.aplayer != null) {
requestAnimationFrame(syncYrc);
};
};
function doLrcSync(lrc) {
if (player.value == null || player.value.aplayer == null) {
return;
};
const playerLyricIndex = player.value.aplayer.lyricIndex;
const output = [[true, 1, playerLyricIndex, 0, lrc]];
if (store.playerLrc.toString() != output.toString()) {
store.setPlayerLrc(output);
return;
};
};
function syncYrc() {
showYrcRunning = 1;
try {
if (player.value == null || player.value.aplayer == null) {
return requestAnimationFrame(syncYrc);
};
const isLineByLine = !store.yrcEnable || store.yrcTemp.length == 0 || store.yrcLoading
if (isLineByLine) {
syncLrc();
return requestAnimationFrame(syncYrc);
} else {
//
const now = player.value.audioStatus.playedTime * 1000;
const yrcFiltered = store.yrcTemp.filter((i) => i[0] < now);
const yrcLyric =
yrcFiltered.length > 0
? yrcFiltered.slice(-1)[0][2].map((it) => {
const [[start, duration], word, line, row] = it;
const isCurrent = now >= start && now <= start + duration;
const isSungLyrics = start + duration < now;
const lessdur = start + duration - now;
return [isCurrent, isSungLyrics, line, row, word, duration, lessdur, "auto"];
})
: [[true, 1, 0, 0, `${store.playerTitle} - ${store.playerArtist}`]];
if (store.playerLrc.toString() != yrcLyric.toString()) {
store.setPlayerLrc(yrcLyric);
};
};
} catch (error) {
console.error(error);
};
return requestAnimationFrame(syncYrc);
};
//
//
defineExpose({ playToggle, changeVolume, changeSong, toggleList });
</script>
@ -456,18 +452,14 @@ defineExpose({ playToggle, changeVolume, changeSong, toggleList });
text-align: left;
margin: 7px 0 6px 6px;
height: 44px;
-webkit-mask: linear-gradient(
#fff 15%,
#fff 85%,
hsla(0deg, 0%, 100%, 0.6) 90%,
hsla(0deg, 0%, 100%, 0)
);
mask: linear-gradient(
#fff 15%,
#fff 85%,
hsla(0deg, 0%, 100%, 0.6) 90%,
hsla(0deg, 0%, 100%, 0)
);
-webkit-mask: linear-gradient(#fff 15%,
#fff 85%,
hsla(0deg, 0%, 100%, 0.6) 90%,
hsla(0deg, 0%, 100%, 0));
mask: linear-gradient(#fff 15%,
#fff 85%,
hsla(0deg, 0%, 100%, 0.6) 90%,
hsla(0deg, 0%, 100%, 0));
&::before,
&::after {