Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .nx/version-plans/version-plan-1786948536412.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
core-bundle: patch
Comment thread
apoint123 marked this conversation as resolved.
---

refactor(core): 统一时间单位
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from "./bg-render/index.ts";
export type * from "./interfaces.ts";
export * from "./lyric-player/index.ts";
export * as spring from "./utils/spring.ts";
export { Duration, MediaTime } from "./utils/time.ts";
9 changes: 5 additions & 4 deletions packages/core/src/lyric-player/base/bottom-line.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Disposable, HasElement } from "#interfaces";
import type { Spring } from "#utils/spring.ts";
import type { Duration } from "#utils/time.ts";

/** 底栏的位移动画弹簧 */
export interface BottomLineTransforms {
Expand Down Expand Up @@ -34,18 +35,18 @@ export interface BottomLine extends HasElement, Disposable {
* @param top 底栏的 Y 坐标
* @param blur 底栏的模糊度
* @param immediate 为 true 时绕过弹簧立刻跳转至目标位置
* @param delay 弹簧过渡的延迟,单位为秒
* @param delay 弹簧过渡的延迟
*/
setTransform(
top?: number,
blur?: number,
immediate?: boolean,
delay?: number,
delay?: Duration,
): void;

/**
* 逐帧推进弹簧动画并应用样式
* @param delta 距离上一次调用的时长,单位为秒
* @param delta 距离上一次调用的时长
*/
update(delta?: number): void;
update(delta?: Duration): void;
}
17 changes: 9 additions & 8 deletions packages/core/src/lyric-player/base/group.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Disposable } from "#interfaces";
import { Spring } from "#utils/spring.ts";
import { Duration, MediaTime } from "#utils/time.ts";
import { LyricLineRenderMode } from "./consts.ts";
import type { LyricLineBase } from "./line.ts";

Expand All @@ -19,7 +20,7 @@ export abstract class LyricLineGroupBase<
public posY: Spring = new Spring(0);
public bgSlideY: Spring = new Spring(-80);
public top = 0;
public delay = 0;
public delay: Duration = Duration.ZERO;

public isActive = false;
public opacity = 1;
Expand All @@ -34,14 +35,14 @@ export abstract class LyricLineGroupBase<
public bgLine?: T | undefined,
) {}

get startTime(): number {
get startTime(): MediaTime {
// 优化歌词时 `syncMainAndBackgroundLines` 已经把时间同步好了,直接读取主歌词的即可
// 要是用户关掉了这个优化,我们认为在这种情况下主歌词和背景人声显示不同步是符合用户预期的
return this.mainLine.getLine().startTime;
return MediaTime.fromMillis(this.mainLine.getLine().startTime);
}

get endTime(): number {
return this.mainLine.getLine().endTime;
get endTime(): MediaTime {
return MediaTime.fromMillis(this.mainLine.getLine().endTime);
}

onLineSizeChange(size: [number, number]): void {
Expand All @@ -56,7 +57,7 @@ export abstract class LyricLineGroupBase<
setTransform(
top: number,
immediate: boolean,
delay: number,
delay: Duration,
isActive: boolean,
opacity: number,
blur: number,
Expand Down Expand Up @@ -90,7 +91,7 @@ export abstract class LyricLineGroupBase<
this.isUiDirty = true;
}

private setLineTransformations(immediate: boolean, delay: number) {
private setLineTransformations(immediate: boolean, delay: Duration) {
const enableScale = this.lyricPlayer.getEnableScale();
const isPlaying = this.lyricPlayer.getIsPlaying();

Expand All @@ -117,7 +118,7 @@ export abstract class LyricLineGroupBase<

abstract get isInSight(): boolean;

update(delta: number): void {
update(delta: Duration = Duration.ZERO): void {
if (this.lyricPlayer.getEnableSpring()) {
const posMoving = !this.posY.arrived();
const bgMoving = !this.bgSlideY.arrived();
Expand Down
39 changes: 24 additions & 15 deletions packages/core/src/lyric-player/base/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import styles from "#styles/lyric-player.module.css";
import { clampPositive } from "#utils/clamp.ts";
import { areOptimizeOptionsEqual } from "#utils/optimize-lyric.ts";
import type { SpringParams } from "#utils/spring.ts";
import { Duration, MediaTime } from "#utils/time.ts";
import type { BottomLine } from "./bottom-line.ts";
import {
LayoutAlignAnchor,
Expand Down Expand Up @@ -180,10 +181,7 @@ export abstract class LyricPlayerBase
private lyricGroupIndexMap = new WeakMap<LyricLineGroupBase, number>();
private onPageShow = () => {
this.isPageVisible = true;
this.setCurrentTime(
this.timelineController.getSnapshot().currentTime,
true,
);
this.setCurrentTime(this.getCurrentTime(), true);
};
private onPageHide = () => {
this.isPageVisible = false;
Expand Down Expand Up @@ -564,9 +562,9 @@ export abstract class LyricPlayerBase
* @param isSeek 这个进度变化是否为跳转触发的
*/
setCurrentTime(time: number, isSeek = false): void {
time = Math.round(time);
const mediaTime = MediaTime.round(MediaTime.fromMillis(time));

const diff = this.timelineController.sync(time, isSeek);
const diff = this.timelineController.sync(mediaTime, isSeek);

if (!diff.hasChanged) {
return;
Expand Down Expand Up @@ -646,7 +644,9 @@ export abstract class LyricPlayerBase
this.buildLyricGroups();

// 对歌词组进行排序,确保滑动窗口与二分查找算法面对的时间线是严格升序的
this.currentLyricGroups.sort((a, b) => a.startTime - b.startTime);
this.currentLyricGroups.sort((a, b) =>
MediaTime.cmp(a.startTime, b.startTime),
);
for (let i = 0; i < this.currentLyricGroups.length; i++) {
this.lyricGroupIndexMap.set(this.currentLyricGroups[i], i);
}
Expand Down Expand Up @@ -689,7 +689,9 @@ export abstract class LyricPlayerBase

let interval: number | undefined;
if (currentGroup && prevGroup) {
interval = currentGroup.startTime - prevGroup.startTime;
interval = Duration.asMillis(
MediaTime.since(currentGroup.startTime, prevGroup.startTime),
);
}

const policy = getPosYSpringPolicy(isSeeking, isInterludeActive, interval);
Expand Down Expand Up @@ -829,8 +831,10 @@ export abstract class LyricPlayerBase
const latestIndex = snapshot.latestHighlightedIndex ?? fallbackFocusIndex;
const activeCount = result.lineCount;

let delay = 0;
let baseDelay = strategy.disableStagger ? 0 : 0.05;
let delay = Duration.ZERO;
let baseDelay = strategy.disableStagger
? Duration.ZERO
: Duration.fromSecs(0.05);

for (let i = 0; i < activeCount; i++) {
const group = this.currentLyricGroups[i];
Expand Down Expand Up @@ -906,8 +910,10 @@ export abstract class LyricPlayerBase
// 应用阶梯式的动画延迟
const lineH = instruction.height;
if (curPos + lineH >= 0 && !snapshot.isSeeking) {
delay += baseDelay;
if (i >= snapshot.scrollToIndex) baseDelay /= 1.05;
delay = Duration.add(delay, baseDelay);
if (i >= snapshot.scrollToIndex) {
baseDelay = Duration.mulF64(baseDelay, 1 / 1.05);
}
}
}

Expand Down Expand Up @@ -1017,8 +1023,9 @@ export abstract class LyricPlayerBase
*/

update(delta = 0): void {
this.bottomLine.update(delta / 1000);
this.interludeDots.update(delta);
const d = Duration.fromMillis(delta);
this.bottomLine.update(d);
this.interludeDots.update(d);
}

protected onResize(): void {}
Expand Down Expand Up @@ -1061,7 +1068,9 @@ export abstract class LyricPlayerBase
* @returns 当前播放位置
*/
getCurrentTime(): number {
return this.timelineController.getSnapshot().currentTime;
return MediaTime.asMillis(
this.timelineController.getSnapshot().currentTime,
);
}

/**
Expand Down
9 changes: 5 additions & 4 deletions packages/core/src/lyric-player/base/interlude-dots.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Disposable, HasElement } from "#interfaces";
import type { Duration, MediaTime } from "#utils/time.ts";

/**
* 间奏点组件的抽象接口
Expand All @@ -16,8 +17,8 @@ export interface InterludeDots extends HasElement, Disposable {
* @param forceReset 是否强制重置动画起点,如 Seek、重新布局或切换间奏时
*/
setInterlude(
interlude?: [number, number],
currentTime?: number,
interlude?: [MediaTime, MediaTime],
currentTime?: MediaTime,
forceReset?: boolean,
): void;

Expand All @@ -33,7 +34,7 @@ export interface InterludeDots extends HasElement, Disposable {

/**
* 逐帧推进间奏点动画并写入样式
* @param delta 距离上一次调用的时长,单位为毫秒
* @param delta 距离上一次调用的时长
*/
update(delta?: number): void;
update(delta?: Duration): void;
}
7 changes: 4 additions & 3 deletions packages/core/src/lyric-player/base/line.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Disposable, LyricLine, LyricWord } from "#interfaces";
import { isCJK } from "#utils/is-cjk.ts";
import { Spring } from "#utils/spring.ts";
import { Duration } from "#utils/time.ts";
import { LyricLineRenderMode } from "./consts.ts";

interface LineTransforms {
Expand All @@ -16,7 +17,7 @@ export abstract class LyricLineBase extends EventTarget implements Disposable {
protected scale = 1;
protected blur = 0;
protected opacity = 1;
protected delay = 0;
protected delay: Duration = Duration.ZERO;

protected isUiDirty = true;

Expand Down Expand Up @@ -54,7 +55,7 @@ export abstract class LyricLineBase extends EventTarget implements Disposable {
opacity: number = this.opacity,
blur: number = this.blur,
_immediate = false,
delay = 0,
delay: Duration = Duration.ZERO,
_mode: LyricLineRenderMode = LyricLineRenderMode.SOLID,
): void {
this.scale = scale;
Expand Down Expand Up @@ -85,6 +86,6 @@ export abstract class LyricLineBase extends EventTarget implements Disposable {
word.word.trim().length > 1
);
}
abstract update(delta?: number): void;
abstract update(delta?: Duration): void;
dispose(): void {}
}
Loading