ref: migrating to Svelte 5
This commit is contained in:
parent
57de9f426f
commit
93855a3f61
@ -26,7 +26,7 @@
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-svelte": "^3.2.3",
|
||||
"svelte": "^4.2.19",
|
||||
"svelte": "^5.2.2",
|
||||
"svelte-check": "^3.7.1",
|
||||
"typescript": "^5.4.5",
|
||||
"vite-plugin-wasm": "^3.3.0",
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { type ScriptItem, type LyricData } from '@alikia/aqualyrics';
|
||||
import { type LyricData, type ScriptItem } from '@alikia/aqualyrics';
|
||||
import { onMount } from 'svelte';
|
||||
import LyricLine from './lyricLine.svelte';
|
||||
import createLyricsSearcher from '@core/lyrics/lyricSearcher';
|
||||
@ -15,38 +15,34 @@
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
// Props
|
||||
export let originalLyrics: LyricData;
|
||||
export let progress: number;
|
||||
export let player: HTMLAudioElement | null;
|
||||
let { originalLyrics, progress, player } : {
|
||||
originalLyrics: LyricData,
|
||||
progress: number,
|
||||
player: HTMLAudioElement | null
|
||||
} = $props();
|
||||
|
||||
// States
|
||||
let lyricLines: ScriptItem[] = [];
|
||||
let lyricExists = false;
|
||||
let lyricsContainer: HTMLDivElement | null;
|
||||
let debugMode = false;
|
||||
let nextUpdate = 0;
|
||||
let lastProgress = 0;
|
||||
let showTranslation = false;
|
||||
let scrollEventAdded = false;
|
||||
let scrolling = false;
|
||||
let scrollingTimeout: Timer;
|
||||
let lastY: number; // For tracking touch movements
|
||||
let lastTime: number; // For tracking time between touch moves
|
||||
let velocityY = 0; // Vertical scroll velocity
|
||||
let inertiaFrame: number; // For storing the requestAnimationFrame reference
|
||||
let lyricLines: ScriptItem[] = $state([]);
|
||||
let lyricsContainer: HTMLDivElement | null = $state(null);
|
||||
let debugMode = $state(false);
|
||||
let nextUpdate = $state(0);
|
||||
let lastProgress = $state(0);
|
||||
let showTranslation = $state(false);
|
||||
let scrollEventAdded = $state(false);
|
||||
let scrolling = $state(false);
|
||||
let scrollingTimeout: Timer | null = $state(null);
|
||||
let lastY: number = $state(0); // For tracking touch movements
|
||||
let lastTime: number = $state(0); // For tracking time between touch moves
|
||||
let velocityY = $state(0); // Vertical scroll velocity
|
||||
let inertiaFrame: number = $state(0); // For storing the requestAnimationFrame reference
|
||||
|
||||
// References to lyric elements
|
||||
let lyricElements: HTMLDivElement[] = [];
|
||||
let lyricComponents: LyricLine[] = [];
|
||||
let lyricTopList: number[] = [];
|
||||
let lyricElements: HTMLDivElement[] = $state([]);
|
||||
let lyricComponents: LyricLine[] = $state([]);
|
||||
let lyricTopList: number[] = $state([]);
|
||||
|
||||
let currentLyricIndex: number;
|
||||
|
||||
$: getLyricIndex = createLyricsSearcher(originalLyrics);
|
||||
|
||||
$: {
|
||||
currentLyricIndex = getLyricIndex(progress);
|
||||
}
|
||||
let getLyricIndex = $derived(createLyricsSearcher(originalLyrics));
|
||||
let currentLyricIndex = $derived(getLyricIndex(progress));
|
||||
|
||||
function initLyricComponents() {
|
||||
initLyricTopList();
|
||||
@ -88,18 +84,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
if (originalLyrics && originalLyrics.scripts) {
|
||||
lyricExists = true;
|
||||
lyricLines = originalLyrics.scripts!;
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
if (lyricComponents.length > 0) {
|
||||
$effect(() => {
|
||||
if (!originalLyrics || !originalLyrics.scripts) return;
|
||||
lyricLines = originalLyrics.scripts!;
|
||||
});
|
||||
let initialized = $state(false);
|
||||
$effect(() => {
|
||||
if (lyricComponents.length > 0 && !initialized) {
|
||||
initLyricComponents();
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function handleScroll(deltaY: number) {
|
||||
for (let i = 0; i < lyricElements.length; i++) {
|
||||
@ -154,52 +149,50 @@
|
||||
inertiaScroll();
|
||||
}
|
||||
|
||||
$: {
|
||||
if (lyricsContainer && !scrollEventAdded) {
|
||||
// Wheel event for desktop
|
||||
lyricsContainer.addEventListener(
|
||||
'wheel',
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
const deltaY = e.deltaY;
|
||||
handleScroll(deltaY);
|
||||
},
|
||||
{ passive: false }
|
||||
);
|
||||
$effect(() => {
|
||||
if (!lyricsContainer || scrollEventAdded) return;
|
||||
// Wheel event for desktop
|
||||
lyricsContainer.addEventListener(
|
||||
'wheel',
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
const deltaY = e.deltaY;
|
||||
handleScroll(deltaY);
|
||||
},
|
||||
{ passive: false }
|
||||
);
|
||||
|
||||
// Touch events for mobile
|
||||
lyricsContainer.addEventListener('touchstart', handleTouchStart, { passive: true });
|
||||
lyricsContainer.addEventListener('touchmove', handleTouchMove, { passive: false });
|
||||
lyricsContainer.addEventListener('touchend', handleTouchEnd, { passive: true });
|
||||
// Touch events for mobile
|
||||
lyricsContainer.addEventListener('touchstart', handleTouchStart, { passive: true });
|
||||
lyricsContainer.addEventListener('touchmove', handleTouchMove, { passive: false });
|
||||
lyricsContainer.addEventListener('touchend', handleTouchEnd, { passive: true });
|
||||
|
||||
scrollEventAdded = true;
|
||||
scrollEventAdded = true;
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (!lyricsContainer || lyricComponents.length < 0) return;
|
||||
if (progress >= nextUpdate - 0.5 && !scrolling) {
|
||||
computeLayout();
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
if (lyricsContainer && lyricComponents.length > 0) {
|
||||
if (progress >= nextUpdate - 0.5 && !scrolling) {
|
||||
computeLayout();
|
||||
}
|
||||
if (Math.abs(lastProgress - progress) > 0.5) {
|
||||
scrolling = false;
|
||||
}
|
||||
if (lastProgress - progress > 0) {
|
||||
computeLayout();
|
||||
nextUpdate = progress;
|
||||
if (Math.abs(lastProgress - progress) > 0.5) {
|
||||
scrolling = false;
|
||||
}
|
||||
if (lastProgress - progress > 0) {
|
||||
computeLayout();
|
||||
nextUpdate = progress;
|
||||
} else {
|
||||
const lyricLength = originalLyrics.scripts!.length;
|
||||
const currentEnd = originalLyrics.scripts![currentLyricIndex].end;
|
||||
const nextStart = originalLyrics.scripts![Math.min(currentLyricIndex + 1, lyricLength - 1)].start;
|
||||
if (currentEnd !== nextStart) {
|
||||
nextUpdate = currentEnd;
|
||||
} else {
|
||||
const lyricLength = originalLyrics.scripts!.length;
|
||||
const currentEnd = originalLyrics.scripts![currentLyricIndex].end;
|
||||
const nextStart = originalLyrics.scripts![Math.min(currentLyricIndex + 1, lyricLength - 1)].start;
|
||||
if (currentEnd !== nextStart) {
|
||||
nextUpdate = currentEnd;
|
||||
} else {
|
||||
nextUpdate = nextStart;
|
||||
}
|
||||
nextUpdate = nextStart;
|
||||
}
|
||||
}
|
||||
lastProgress = progress;
|
||||
}
|
||||
});
|
||||
|
||||
// $: {
|
||||
// for (let i = 0; i < lyricElements.length; i++) {
|
||||
@ -243,32 +236,14 @@
|
||||
player.currentTime = originalLyrics.scripts[lyricIndex].start;
|
||||
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>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown} />
|
||||
<!--<svelte:window on:keydown={onKeyDown} />-->
|
||||
|
||||
{#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">
|
||||
{fps.toFixed(1)}fps, progress: {progress.toFixed(2)}, nextUpdate: {nextUpdate}, scrolling: {scrolling}, current: {currentLyricIndex}
|
||||
<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">
|
||||
progress: {progress.toFixed(2)}, nextUpdate: {nextUpdate}, scrolling: {scrolling}, current: {currentLyricIndex}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-svelte": "^3.2.3",
|
||||
"svelte": "^4.2.19",
|
||||
"svelte": "^5.2.2",
|
||||
"svelte-check": "^3.7.1",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"typescript": "^5.4.5",
|
||||
|
@ -26,7 +26,7 @@
|
||||
"postcss": "^8.4.49",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.8",
|
||||
"svelte": "^4.2.19",
|
||||
"svelte": "^5.2.2",
|
||||
"svelte-check": "^3.8.6",
|
||||
"tailwindcss": "^3.4.15",
|
||||
"typescript": "^5.6.3",
|
||||
|
@ -3,6 +3,8 @@
|
||||
import getVersion from '@core/utils/getVersion';
|
||||
import toHumanSize from '@core/utils/humanSize';
|
||||
import localforage from '@core/utils/storage';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
interface Song {
|
||||
name: string;
|
||||
singer?: string;
|
||||
@ -58,7 +60,9 @@
|
||||
<div>
|
||||
<ul class="mt-4 relative w-full">
|
||||
{#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
|
||||
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}
|
||||
</li>
|
||||
</a>
|
||||
</div>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
@ -83,7 +87,7 @@
|
||||
</p>
|
||||
<a href="/import">导入音乐</a> <br />
|
||||
<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
|
||||
>
|
||||
<h2 class="mt-4"><a href="/database/">音乐数据库</a></h2>
|
||||
|
@ -87,12 +87,9 @@
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// 计算新的宽度和高度,确保宽度至少为1200px
|
||||
let newWidth = img.width;
|
||||
let newHeight = img.height;
|
||||
|
||||
console.log(newWidth)
|
||||
|
||||
if (newWidth < 1200) {
|
||||
newWidth = 1200;
|
||||
newHeight = (img.height * 1200) / img.width;
|
||||
@ -101,14 +98,12 @@
|
||||
canvas.width = newWidth;
|
||||
canvas.height = newHeight;
|
||||
|
||||
// 绘制放大后的图片到canvas
|
||||
ctx!.drawImage(img, 0, 0, newWidth, newHeight);
|
||||
|
||||
// 将canvas内容转换为Blob
|
||||
canvas.toBlob(function (blob) {
|
||||
const path = URL.createObjectURL(blob!);
|
||||
coverPath.set(path);
|
||||
}, 'image/jpeg'); // 你可以根据需要更改图片格式
|
||||
}, 'image/jpeg');
|
||||
|
||||
prepared.push('cover');
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user