@linker-design-plus/timeline-track 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/dist/components/Timeline.d.ts +20 -1
- package/dist/components/VideoTrack.d.ts +12 -1
- package/dist/core/constants.d.ts +1 -0
- package/dist/core/timelineManager.d.ts +50 -3
- package/dist/core/types.d.ts +12 -1
- package/dist/index.cjs.js +3 -3
- package/dist/index.es.js +2281 -1971
- package/dist/utils/KonvaUtils.d.ts +12 -4
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -348,6 +348,12 @@ new TimelineManager(config?: Partial<TimelineConfig>)
|
|
|
348
348
|
| `off(event, listener)` | 移除事件监听器 | `event`:事件类型,`listener`:事件监听器 | 无 |
|
|
349
349
|
| `destroy()` | 销毁时间轴管理器 | 无 | 无 |
|
|
350
350
|
|
|
351
|
+
### 交互事件分层规范
|
|
352
|
+
|
|
353
|
+
- 鼠标交互(时间轴拖拽、底部滑块拖拽、片段拖拽)采用统一分层策略,详见:
|
|
354
|
+
- `docs/interaction-model.md`
|
|
355
|
+
- 该文档用于约束后续重构,避免出现“移出画布中断拖拽”或“回到画布瞬移”等回归问题。
|
|
356
|
+
|
|
351
357
|
#### 事件
|
|
352
358
|
|
|
353
359
|
| 事件名 | 描述 | 数据 |
|
|
@@ -359,9 +365,13 @@ new TimelineManager(config?: Partial<TimelineConfig>)
|
|
|
359
365
|
| `clip_removed` | 移除片段 | `{ clipId: string }` |
|
|
360
366
|
| `clip_updated` | 更新片段 | `{ clip: Clip }` |
|
|
361
367
|
| `clip_selected` | 选择片段 | `{ clip: Clip }` |
|
|
368
|
+
| `selected_clip_change` | 选中片段变化(订阅后会立即回调当前状态) | `{ clip: Clip \| null, hasSelectedClip: boolean }` |
|
|
362
369
|
| `zoom_change` | 缩放比例变化 | `{ zoom: number }` |
|
|
363
370
|
| `history_change` | 历史记录变更 | `{ canUndo: boolean, canRedo: boolean }` |
|
|
364
371
|
| `track_duration_change` | 轨道总时长变化 | `{ duration: number }` |
|
|
372
|
+
| `buffering_state_change` | 视频缓冲状态变化 | `{ isBuffering: boolean }` |
|
|
373
|
+
| `can_play_change` | 是否可播放状态变化 | `{ canPlay: boolean }` |
|
|
374
|
+
| `source_loading_change` | 视频源加载状态变化 | `{ isLoading: boolean, pending: number }` |
|
|
365
375
|
|
|
366
376
|
### ClipConfig 接口
|
|
367
377
|
|
|
@@ -13,15 +13,26 @@ export declare class Timeline {
|
|
|
13
13
|
private onZoomChange;
|
|
14
14
|
private onScrollChange;
|
|
15
15
|
private animationFrameId;
|
|
16
|
-
private isZooming;
|
|
17
16
|
private scrollbarHeight;
|
|
18
17
|
private scrollbarY;
|
|
19
18
|
private isScrollbarDragging;
|
|
20
19
|
private scrollbarDragStartX;
|
|
21
20
|
private scrollbarDragStartScrollLeft;
|
|
21
|
+
private hasBoundGlobalPointerListenersForDrag;
|
|
22
|
+
private isPointerInsideTimeline;
|
|
23
|
+
private lastPointerXInTimeline;
|
|
24
|
+
private handleGlobalPointerMove;
|
|
25
|
+
private handleGlobalPointerEnd;
|
|
26
|
+
private handleVisibilityChange;
|
|
22
27
|
private leftPadding;
|
|
23
28
|
constructor(stage: Konva.Stage, gridLayer: Konva.Layer, config: Partial<TimelineConfig>, onTimeChange: (time: TimeMs) => void, onZoomChange: (zoom: number) => void, onScrollChange: (scrollLeft: number) => void);
|
|
24
29
|
private initEventListeners;
|
|
30
|
+
private updatePointerPosition;
|
|
31
|
+
private bindGlobalPointerListenersForDrag;
|
|
32
|
+
private unbindGlobalPointerListenersForDrag;
|
|
33
|
+
private isPointerSessionActive;
|
|
34
|
+
private finalizePointerInteraction;
|
|
35
|
+
private handlePointerMove;
|
|
25
36
|
private handleZoom;
|
|
26
37
|
private animateZoom;
|
|
27
38
|
private animateHorizontalScroll;
|
|
@@ -64,6 +75,14 @@ export declare class Timeline {
|
|
|
64
75
|
* 获取网格图层
|
|
65
76
|
*/
|
|
66
77
|
getGridLayer(): Konva.Layer;
|
|
78
|
+
/**
|
|
79
|
+
* 鼠标当前是否位于时间轴区域内
|
|
80
|
+
*/
|
|
81
|
+
hasPointerInTimeline(): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* 获取时间轴内最近一次鼠标 X 坐标(相对 stage)
|
|
84
|
+
*/
|
|
85
|
+
getPointerXInTimeline(): number | null;
|
|
67
86
|
/**
|
|
68
87
|
* 调整大小
|
|
69
88
|
*/
|
|
@@ -21,13 +21,21 @@ export declare class VideoTrack {
|
|
|
21
21
|
private onClipSplit;
|
|
22
22
|
private onClipSelect;
|
|
23
23
|
private onTimeJump;
|
|
24
|
+
private onAutoScrollDuringDrag?;
|
|
25
|
+
private dragAutoScrollOffsetPx;
|
|
26
|
+
private hasBoundGlobalPointerListenersForDrag;
|
|
27
|
+
private handleGlobalPointerMove;
|
|
28
|
+
private handleGlobalPointerEnd;
|
|
24
29
|
constructor(layer: Konva.Layer, config: TrackConfig, zoom: number, trackY: number, trackHeight: number, theme: Theme, onClipUpdate: (clip: ClipType, originalClip?: ClipType, clipUpdates?: Array<{
|
|
25
30
|
clipId: string;
|
|
26
31
|
newState: any;
|
|
27
32
|
previousState: any;
|
|
28
|
-
}>) => void, onClipAdd: (clip: ClipType) => void, onClipRemove: (clipId: string) => void, onClipSplit: (clip1: ClipType, clip2: ClipType) => void, onClipSelect: (clip: ClipType) => void, onTimeJump: (time: TimeMs) => void);
|
|
33
|
+
}>) => void, onClipAdd: (clip: ClipType) => void, onClipRemove: (clipId: string) => void, onClipSplit: (clip1: ClipType, clip2: ClipType) => void, onClipSelect: (clip: ClipType) => void, onTimeJump: (time: TimeMs) => void, onAutoScrollDuringDrag?: (targetScrollLeft: number) => void);
|
|
29
34
|
private initClips;
|
|
30
35
|
private initEventListeners;
|
|
36
|
+
private bindGlobalPointerListenersForDrag;
|
|
37
|
+
private unbindGlobalPointerListenersForDrag;
|
|
38
|
+
private handleVisibilityChange;
|
|
31
39
|
/**
|
|
32
40
|
* 处理轨道背景点击事件
|
|
33
41
|
*/
|
|
@@ -77,6 +85,9 @@ export declare class VideoTrack {
|
|
|
77
85
|
* 处理舞台鼠标移动事件
|
|
78
86
|
*/
|
|
79
87
|
private handleStageMouseMove;
|
|
88
|
+
private isDragSessionActive;
|
|
89
|
+
private handleDragMove;
|
|
90
|
+
private maybeAutoScrollDuringDrag;
|
|
80
91
|
/**
|
|
81
92
|
* 处理片段鼠标离开事件
|
|
82
93
|
*/
|
package/dist/core/constants.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TimelineConfig, Clip, ClipConfig, TimeMs, PlayState, Action, TimelineEvent, EventListener, VideoPreviewConfig, TimelineExportData, ThumbnailProvider } from './types';
|
|
1
|
+
import { TimelineConfig, Clip, ClipConfig, TimeMs, PlayState, Action, TimelineEvent, EventListener as TimelineEventListener, VideoPreviewConfig, TimelineExportData, ThumbnailProvider } from './types';
|
|
2
2
|
export declare class TimelineManager {
|
|
3
3
|
private timeline;
|
|
4
4
|
private tracks;
|
|
@@ -20,6 +20,12 @@ export declare class TimelineManager {
|
|
|
20
20
|
private lastTrackDuration;
|
|
21
21
|
private thumbnailProvider;
|
|
22
22
|
private canPlay;
|
|
23
|
+
private isBuffering;
|
|
24
|
+
private sourceLoadingCount;
|
|
25
|
+
private lastSelectedClipId;
|
|
26
|
+
private playStateBeforeBuffering;
|
|
27
|
+
private isPausingForBuffering;
|
|
28
|
+
private videoBufferingListeners;
|
|
23
29
|
constructor(config?: Partial<TimelineConfig>);
|
|
24
30
|
init(container: HTMLElement): void;
|
|
25
31
|
play(): void;
|
|
@@ -29,6 +35,21 @@ export declare class TimelineManager {
|
|
|
29
35
|
setCurrentTime(time: TimeMs): void;
|
|
30
36
|
getCurrentTime(): TimeMs;
|
|
31
37
|
setZoom(zoom: number): void;
|
|
38
|
+
/**
|
|
39
|
+
* 以游标(playhead)为中心设置缩放,用于外置 slider 等非幕布上的缩放操作
|
|
40
|
+
* 调整 scrollLeft 使游标在屏幕上的位置保持不变
|
|
41
|
+
*/
|
|
42
|
+
setZoomCenteredOnPlayhead(zoom: number): void;
|
|
43
|
+
/**
|
|
44
|
+
* 外部缩放入口:
|
|
45
|
+
* - 鼠标在时间轴内:以鼠标位置为中心缩放
|
|
46
|
+
* - 鼠标不在时间轴内:回退为以游标(playhead)为中心缩放
|
|
47
|
+
*/
|
|
48
|
+
setZoomByInteraction(zoom: number): void;
|
|
49
|
+
/**
|
|
50
|
+
* 以时间轴上的指定像素点为中心缩放,保持该像素对应时间不变
|
|
51
|
+
*/
|
|
52
|
+
setZoomCenteredOnTimelinePointer(zoom: number, pointerX: number): void;
|
|
32
53
|
getZoom(): number;
|
|
33
54
|
/**
|
|
34
55
|
* 设置播放倍速
|
|
@@ -45,6 +66,17 @@ export declare class TimelineManager {
|
|
|
45
66
|
* @returns 是否可以播放
|
|
46
67
|
*/
|
|
47
68
|
getCanPlay(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* 当前是否存在视频源加载任务(例如 addClip 期间读取视频时长)
|
|
71
|
+
*/
|
|
72
|
+
isSourceLoading(): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* 获取视频源加载状态
|
|
75
|
+
*/
|
|
76
|
+
getSourceLoadingState(): {
|
|
77
|
+
isLoading: boolean;
|
|
78
|
+
pending: number;
|
|
79
|
+
};
|
|
48
80
|
/**
|
|
49
81
|
* 设置缩略图提供器
|
|
50
82
|
* @param provider 缩略图提供器
|
|
@@ -68,6 +100,11 @@ export declare class TimelineManager {
|
|
|
68
100
|
*/
|
|
69
101
|
refreshAllClipThumbnails(): Promise<boolean[]>;
|
|
70
102
|
addClip(clipConfig: ClipConfig): Promise<string>;
|
|
103
|
+
/**
|
|
104
|
+
* 批量添加片段。批量模式下仅维护一段连续的视频源加载状态。
|
|
105
|
+
*/
|
|
106
|
+
addClips(clipConfigs: ClipConfig[]): Promise<string[]>;
|
|
107
|
+
private addClipInternal;
|
|
71
108
|
removeClip(clipId: string): void;
|
|
72
109
|
updateClip(clipId: string, updates: Partial<Clip>): void;
|
|
73
110
|
splitClip(clipId: string, time: TimeMs): void;
|
|
@@ -92,6 +129,7 @@ export declare class TimelineManager {
|
|
|
92
129
|
private handleTimeChange;
|
|
93
130
|
private handleZoomChange;
|
|
94
131
|
private handleScrollChange;
|
|
132
|
+
private handleTrackAutoScrollRequest;
|
|
95
133
|
private handleClipUpdate;
|
|
96
134
|
private handleClipAdd;
|
|
97
135
|
private handleClipRemove;
|
|
@@ -109,9 +147,12 @@ export declare class TimelineManager {
|
|
|
109
147
|
private handleClipSelect;
|
|
110
148
|
private handleActionUndo;
|
|
111
149
|
private handleActionRedo;
|
|
112
|
-
on(event: TimelineEvent, listener:
|
|
113
|
-
off(event: TimelineEvent, listener:
|
|
150
|
+
on(event: TimelineEvent, listener: TimelineEventListener): void;
|
|
151
|
+
off(event: TimelineEvent, listener: TimelineEventListener): void;
|
|
114
152
|
private emitEvent;
|
|
153
|
+
private emitSelectedClipChangeIfNeeded;
|
|
154
|
+
private beginSourceLoading;
|
|
155
|
+
private endSourceLoading;
|
|
115
156
|
getPlayState(): PlayState;
|
|
116
157
|
setDuration(duration: TimeMs): void;
|
|
117
158
|
getDuration(): TimeMs;
|
|
@@ -168,10 +209,16 @@ export declare class TimelineManager {
|
|
|
168
209
|
/** 清除历史堆栈 */
|
|
169
210
|
clearHistory(): void;
|
|
170
211
|
private handleVideoTimeUpdate;
|
|
212
|
+
private getLastClipByEndTime;
|
|
171
213
|
private handlePlayStateChange;
|
|
172
214
|
private handleClipChange;
|
|
173
215
|
private findClipAtTime;
|
|
174
216
|
private loadClipToVideo;
|
|
217
|
+
private attachVideoBufferingListeners;
|
|
218
|
+
private detachVideoBufferingListeners;
|
|
219
|
+
private enterBuffering;
|
|
220
|
+
private exitBuffering;
|
|
221
|
+
private clearBufferingStateForNoSource;
|
|
175
222
|
/**
|
|
176
223
|
* 检查轨道总时长是否变化,如果变化则触发事件并更新时间轴时长
|
|
177
224
|
*/
|
package/dist/core/types.d.ts
CHANGED
|
@@ -123,7 +123,7 @@ export interface HistoryState {
|
|
|
123
123
|
past: Action[];
|
|
124
124
|
future: Action[];
|
|
125
125
|
}
|
|
126
|
-
export type TimelineEvent = 'time_change' | 'play_state_change' | 'clip_added' | 'clip_removed' | 'clip_updated' | 'zoom_change' | 'history_change' | 'track_duration_change' | 'clip_selected' | 'speed_change' | 'can_play_change';
|
|
126
|
+
export type TimelineEvent = 'time_change' | 'play_state_change' | 'clip_added' | 'clip_removed' | 'clip_updated' | 'zoom_change' | 'history_change' | 'track_duration_change' | 'clip_selected' | 'selected_clip_change' | 'speed_change' | 'can_play_change' | 'buffering_state_change' | 'source_loading_change';
|
|
127
127
|
export interface TimeChangeData {
|
|
128
128
|
time: TimeMs;
|
|
129
129
|
}
|
|
@@ -136,12 +136,23 @@ export interface ZoomChangeData {
|
|
|
136
136
|
export interface ClipEventData {
|
|
137
137
|
clip: Clip;
|
|
138
138
|
}
|
|
139
|
+
export interface SelectedClipChangeData {
|
|
140
|
+
clip: Clip | null;
|
|
141
|
+
hasSelectedClip: boolean;
|
|
142
|
+
}
|
|
139
143
|
export interface ClipRemovedEventData {
|
|
140
144
|
clipId: string;
|
|
141
145
|
}
|
|
142
146
|
export interface CanPlayChangeData {
|
|
143
147
|
canPlay: boolean;
|
|
144
148
|
}
|
|
149
|
+
export interface BufferingStateChangeData {
|
|
150
|
+
isBuffering: boolean;
|
|
151
|
+
}
|
|
152
|
+
export interface SourceLoadingChangeData {
|
|
153
|
+
isLoading: boolean;
|
|
154
|
+
pending: number;
|
|
155
|
+
}
|
|
145
156
|
export interface EventListener {
|
|
146
157
|
(event: TimelineEvent, data?: any): void;
|
|
147
158
|
}
|