ref: migrating to Svelte 5
This commit is contained in:
parent
57de9f426f
commit
93855a3f61
@ -26,7 +26,7 @@
|
|||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-svelte": "^3.2.3",
|
"prettier-plugin-svelte": "^3.2.3",
|
||||||
"svelte": "^4.2.19",
|
"svelte": "^5.2.2",
|
||||||
"svelte-check": "^3.7.1",
|
"svelte-check": "^3.7.1",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
"vite-plugin-wasm": "^3.3.0",
|
"vite-plugin-wasm": "^3.3.0",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type ScriptItem, type LyricData } from '@alikia/aqualyrics';
|
import { type LyricData, type ScriptItem } from '@alikia/aqualyrics';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import LyricLine from './lyricLine.svelte';
|
import LyricLine from './lyricLine.svelte';
|
||||||
import createLyricsSearcher from '@core/lyrics/lyricSearcher';
|
import createLyricsSearcher from '@core/lyrics/lyricSearcher';
|
||||||
@ -15,38 +15,34 @@
|
|||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
export let originalLyrics: LyricData;
|
let { originalLyrics, progress, player } : {
|
||||||
export let progress: number;
|
originalLyrics: LyricData,
|
||||||
export let player: HTMLAudioElement | null;
|
progress: number,
|
||||||
|
player: HTMLAudioElement | null
|
||||||
|
} = $props();
|
||||||
|
|
||||||
// States
|
// States
|
||||||
let lyricLines: ScriptItem[] = [];
|
let lyricLines: ScriptItem[] = $state([]);
|
||||||
let lyricExists = false;
|
let lyricsContainer: HTMLDivElement | null = $state(null);
|
||||||
let lyricsContainer: HTMLDivElement | null;
|
let debugMode = $state(false);
|
||||||
let debugMode = false;
|
let nextUpdate = $state(0);
|
||||||
let nextUpdate = 0;
|
let lastProgress = $state(0);
|
||||||
let lastProgress = 0;
|
let showTranslation = $state(false);
|
||||||
let showTranslation = false;
|
let scrollEventAdded = $state(false);
|
||||||
let scrollEventAdded = false;
|
let scrolling = $state(false);
|
||||||
let scrolling = false;
|
let scrollingTimeout: Timer | null = $state(null);
|
||||||
let scrollingTimeout: Timer;
|
let lastY: number = $state(0); // For tracking touch movements
|
||||||
let lastY: number; // For tracking touch movements
|
let lastTime: number = $state(0); // For tracking time between touch moves
|
||||||
let lastTime: number; // For tracking time between touch moves
|
let velocityY = $state(0); // Vertical scroll velocity
|
||||||
let velocityY = 0; // Vertical scroll velocity
|
let inertiaFrame: number = $state(0); // For storing the requestAnimationFrame reference
|
||||||
let inertiaFrame: number; // For storing the requestAnimationFrame reference
|
|
||||||
|
|
||||||
// References to lyric elements
|
// References to lyric elements
|
||||||
let lyricElements: HTMLDivElement[] = [];
|
let lyricElements: HTMLDivElement[] = $state([]);
|
||||||
let lyricComponents: LyricLine[] = [];
|
let lyricComponents: LyricLine[] = $state([]);
|
||||||
let lyricTopList: number[] = [];
|
let lyricTopList: number[] = $state([]);
|
||||||
|
|
||||||
let currentLyricIndex: number;
|
let getLyricIndex = $derived(createLyricsSearcher(originalLyrics));
|
||||||
|
let currentLyricIndex = $derived(getLyricIndex(progress));
|
||||||
$: getLyricIndex = createLyricsSearcher(originalLyrics);
|
|
||||||
|
|
||||||
$: {
|
|
||||||
currentLyricIndex = getLyricIndex(progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
function initLyricComponents() {
|
function initLyricComponents() {
|
||||||
initLyricTopList();
|
initLyricTopList();
|
||||||
@ -88,18 +84,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: {
|
$effect(() => {
|
||||||
if (originalLyrics && originalLyrics.scripts) {
|
if (!originalLyrics || !originalLyrics.scripts) return;
|
||||||
lyricExists = true;
|
|
||||||
lyricLines = originalLyrics.scripts!;
|
lyricLines = originalLyrics.scripts!;
|
||||||
}
|
});
|
||||||
}
|
let initialized = $state(false);
|
||||||
|
$effect(() => {
|
||||||
$: {
|
if (lyricComponents.length > 0 && !initialized) {
|
||||||
if (lyricComponents.length > 0) {
|
|
||||||
initLyricComponents();
|
initLyricComponents();
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
function handleScroll(deltaY: number) {
|
function handleScroll(deltaY: number) {
|
||||||
for (let i = 0; i < lyricElements.length; i++) {
|
for (let i = 0; i < lyricElements.length; i++) {
|
||||||
@ -154,8 +149,8 @@
|
|||||||
inertiaScroll();
|
inertiaScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
$: {
|
$effect(() => {
|
||||||
if (lyricsContainer && !scrollEventAdded) {
|
if (!lyricsContainer || scrollEventAdded) return;
|
||||||
// Wheel event for desktop
|
// Wheel event for desktop
|
||||||
lyricsContainer.addEventListener(
|
lyricsContainer.addEventListener(
|
||||||
'wheel',
|
'wheel',
|
||||||
@ -173,11 +168,10 @@
|
|||||||
lyricsContainer.addEventListener('touchend', handleTouchEnd, { passive: true });
|
lyricsContainer.addEventListener('touchend', handleTouchEnd, { passive: true });
|
||||||
|
|
||||||
scrollEventAdded = true;
|
scrollEventAdded = true;
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
$: {
|
$effect(() => {
|
||||||
if (lyricsContainer && lyricComponents.length > 0) {
|
if (!lyricsContainer || lyricComponents.length < 0) return;
|
||||||
if (progress >= nextUpdate - 0.5 && !scrolling) {
|
if (progress >= nextUpdate - 0.5 && !scrolling) {
|
||||||
computeLayout();
|
computeLayout();
|
||||||
}
|
}
|
||||||
@ -197,9 +191,8 @@
|
|||||||
nextUpdate = nextStart;
|
nextUpdate = nextStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
lastProgress = progress;
|
lastProgress = progress;
|
||||||
}
|
});
|
||||||
|
|
||||||
// $: {
|
// $: {
|
||||||
// for (let i = 0; i < lyricElements.length; i++) {
|
// for (let i = 0; i < lyricElements.length; i++) {
|
||||||
@ -243,32 +236,14 @@
|
|||||||
player.currentTime = originalLyrics.scripts[lyricIndex].start;
|
player.currentTime = originalLyrics.scripts[lyricIndex].start;
|
||||||
player.play();
|
player.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastFPSTime = performance.now();
|
|
||||||
let frameCount = 0;
|
|
||||||
let fps = 0;
|
|
||||||
|
|
||||||
function calculateFPS(t: number) {
|
|
||||||
// 计算时间差
|
|
||||||
const deltaTime = t - lastFPSTime;
|
|
||||||
frameCount ++;
|
|
||||||
if (frameCount % 5 == 0) {
|
|
||||||
fps = 1000 / deltaTime;
|
|
||||||
}
|
|
||||||
lastFPSTime = t;
|
|
||||||
// 请求下一帧
|
|
||||||
requestAnimationFrame(calculateFPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始检测帧率
|
|
||||||
requestAnimationFrame(calculateFPS);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window on:keydown={onKeyDown} />
|
<!--<svelte:window on:keydown={onKeyDown} />-->
|
||||||
|
|
||||||
{#if debugMode}
|
{#if debugMode}
|
||||||
<span class="text-white text-lg absolute z-50 px-2 py-0.5 m-2 rounded-3xl bg-white bg-opacity-20 backdrop-blur-lg right-0 font-mono">
|
<span
|
||||||
{fps.toFixed(1)}fps, progress: {progress.toFixed(2)}, nextUpdate: {nextUpdate}, scrolling: {scrolling}, current: {currentLyricIndex}
|
class="text-white text-lg absolute z-50 px-2 py-0.5 m-2 rounded-3xl bg-white bg-opacity-20 backdrop-blur-lg right-0 font-mono">
|
||||||
|
progress: {progress.toFixed(2)}, nextUpdate: {nextUpdate}, scrolling: {scrolling}, current: {currentLyricIndex}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-svelte": "^3.2.3",
|
"prettier-plugin-svelte": "^3.2.3",
|
||||||
"svelte": "^4.2.19",
|
"svelte": "^5.2.2",
|
||||||
"svelte-check": "^3.7.1",
|
"svelte-check": "^3.7.1",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
"postcss": "^8.4.49",
|
"postcss": "^8.4.49",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"prettier-plugin-svelte": "^3.2.8",
|
"prettier-plugin-svelte": "^3.2.8",
|
||||||
"svelte": "^4.2.19",
|
"svelte": "^5.2.2",
|
||||||
"svelte-check": "^3.8.6",
|
"svelte-check": "^3.8.6",
|
||||||
"tailwindcss": "^3.4.15",
|
"tailwindcss": "^3.4.15",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.6.3",
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
import getVersion from '@core/utils/getVersion';
|
import getVersion from '@core/utils/getVersion';
|
||||||
import toHumanSize from '@core/utils/humanSize';
|
import toHumanSize from '@core/utils/humanSize';
|
||||||
import localforage from '@core/utils/storage';
|
import localforage from '@core/utils/storage';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
interface Song {
|
interface Song {
|
||||||
name: string;
|
name: string;
|
||||||
singer?: string;
|
singer?: string;
|
||||||
@ -58,7 +60,9 @@
|
|||||||
<div>
|
<div>
|
||||||
<ul class="mt-4 relative w-full">
|
<ul class="mt-4 relative w-full">
|
||||||
{#each idList as id}
|
{#each idList as id}
|
||||||
<a class="!no-underline !text-black dark:!text-white" href={`/play/${id}`}>
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
|
<div class="!no-underline !text-black dark:!text-white" onclick={() => goto(`/play/${id}`)}>
|
||||||
<li
|
<li
|
||||||
class="relative my-4 p-4 duration-150 bg-zinc-200 hover:bg-zinc-300 dark:bg-zinc-700 dark:hover:bg-zinc-600 rounded-lg"
|
class="relative my-4 p-4 duration-150 bg-zinc-200 hover:bg-zinc-300 dark:bg-zinc-700 dark:hover:bg-zinc-600 rounded-lg"
|
||||||
>
|
>
|
||||||
@ -73,7 +77,7 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
</a>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -83,7 +87,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<a href="/import">导入音乐</a> <br />
|
<a href="/import">导入音乐</a> <br />
|
||||||
<button
|
<button
|
||||||
on:click={() => window.confirm('确定要删除本地数据库中所有内容吗?') && clear()}
|
onclick={() => window.confirm('确定要删除本地数据库中所有内容吗?') && clear()}
|
||||||
class="text-white bg-red-500 px-4 py-2 mt-4 rounded-md">一键清除</button
|
class="text-white bg-red-500 px-4 py-2 mt-4 rounded-md">一键清除</button
|
||||||
>
|
>
|
||||||
<h2 class="mt-4"><a href="/database/">音乐数据库</a></h2>
|
<h2 class="mt-4"><a href="/database/">音乐数据库</a></h2>
|
||||||
|
@ -87,12 +87,9 @@
|
|||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
// 计算新的宽度和高度,确保宽度至少为1200px
|
|
||||||
let newWidth = img.width;
|
let newWidth = img.width;
|
||||||
let newHeight = img.height;
|
let newHeight = img.height;
|
||||||
|
|
||||||
console.log(newWidth)
|
|
||||||
|
|
||||||
if (newWidth < 1200) {
|
if (newWidth < 1200) {
|
||||||
newWidth = 1200;
|
newWidth = 1200;
|
||||||
newHeight = (img.height * 1200) / img.width;
|
newHeight = (img.height * 1200) / img.width;
|
||||||
@ -101,14 +98,12 @@
|
|||||||
canvas.width = newWidth;
|
canvas.width = newWidth;
|
||||||
canvas.height = newHeight;
|
canvas.height = newHeight;
|
||||||
|
|
||||||
// 绘制放大后的图片到canvas
|
|
||||||
ctx!.drawImage(img, 0, 0, newWidth, newHeight);
|
ctx!.drawImage(img, 0, 0, newWidth, newHeight);
|
||||||
|
|
||||||
// 将canvas内容转换为Blob
|
|
||||||
canvas.toBlob(function (blob) {
|
canvas.toBlob(function (blob) {
|
||||||
const path = URL.createObjectURL(blob!);
|
const path = URL.createObjectURL(blob!);
|
||||||
coverPath.set(path);
|
coverPath.set(path);
|
||||||
}, 'image/jpeg'); // 你可以根据需要更改图片格式
|
}, 'image/jpeg');
|
||||||
|
|
||||||
prepared.push('cover');
|
prepared.push('cover');
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user