@linker-design-plus/timeline-track 1.0.1 → 1.0.3

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 CHANGED
@@ -19,6 +19,8 @@
19
19
  - ✅ 历史记录变更通知事件,用于外部应用调整撤销/重做按钮状态
20
20
  - ✅ 播放倍速控制,支持 0.1x 到 10x 的播放速度
21
21
  - ✅ 轨道总时长计算,包含片段间隙
22
+ - ✅ 封面系统,支持自定义缩略图提供器
23
+ - ✅ 异步封面加载,支持 Promise 形式的封面获取
22
24
 
23
25
  ## 安装
24
26
 
@@ -51,7 +53,8 @@ const clipId = await timelineManager.addClip({
51
53
  src: 'sample-video.mp4',
52
54
  name: 'Clip 1',
53
55
  startTimeAtSource: 0, // 源视频中的开始时间(毫秒)
54
- duration: 5000 // 片段持续时间(毫秒)
56
+ duration: 5000, // 片段持续时间(毫秒)
57
+ thumbnail: 'https://example.com/thumbnail1.jpg' // 可选:直接提供封面图片
55
58
  });
56
59
 
57
60
  // 开始播放
@@ -80,6 +83,44 @@ timelineManager.on('history_change', (event, data) => {
80
83
  // timelineManager.destroy();
81
84
  ```
82
85
 
86
+ ### 封面系统用法
87
+
88
+ ```typescript
89
+ import { TimelineManager, ThumbnailProvider } from '@linker-design-plus/timeline-track';
90
+
91
+ // 创建缩略图提供器
92
+ const thumbnailProvider: ThumbnailProvider = {
93
+ getThumbnail(clip) {
94
+ // 同步获取封面
95
+ return `https://example.com/thumbnails/${clip.id}.jpg`;
96
+
97
+ // 或异步获取封面
98
+ // return new Promise((resolve) => {
99
+ // // 模拟异步获取封面
100
+ // setTimeout(() => {
101
+ // resolve(`https://example.com/thumbnails/${clip.id}.jpg`);
102
+ // }, 100);
103
+ // });
104
+ }
105
+ };
106
+
107
+ // 创建 TimelineManager 实例时设置缩略图提供器
108
+ const timelineManager = new TimelineManager({
109
+ container: timelineContainer,
110
+ thumbnailProvider: thumbnailProvider
111
+ });
112
+
113
+ // 或动态设置缩略图提供器
114
+ timelineManager.setThumbnailProvider(thumbnailProvider);
115
+
116
+ // 添加片段时,会自动通过提供器获取封面
117
+ const clipId = await timelineManager.addClip({
118
+ src: 'sample-video.mp4',
119
+ name: 'Clip 1',
120
+ duration: 5000
121
+ });
122
+ ```
123
+
83
124
  ### Vue 3 集成
84
125
 
85
126
  ```vue
@@ -272,6 +313,7 @@ new TimelineManager(config?: Partial<TimelineConfig>)
272
313
  - `currentTime`:初始当前时间(毫秒),默认 0
273
314
  - `playState`:初始播放状态,默认 'paused'
274
315
  - `speed`:初始播放倍速,默认 1.0
316
+ - `thumbnailProvider`:缩略图提供器,用于获取片段封面
275
317
 
276
318
  #### 核心方法
277
319
 
@@ -285,7 +327,8 @@ new TimelineManager(config?: Partial<TimelineConfig>)
285
327
  | `setZoom(zoom)` | 设置缩放比例 | `zoom`:缩放比例(像素/秒) | 无 |
286
328
  | `getZoom()` | 获取缩放比例 | 无 | `number` |
287
329
  | `setSpeed(speed)` | 设置播放倍速 | `speed`:播放倍速 | 无 |
288
- | `getSpeed()` | 获取播放倍速 | 无 | `number` |
330
+ | `getSpeed()` | 获取当前播放倍速 | 无 | `number` |
331
+ | `setThumbnailProvider(provider)` | 设置缩略图提供器 | `provider`:缩略图提供器 | 无 |
289
332
  | `addClip(clipConfig)` | 添加片段 | `clipConfig`:片段配置 | `Promise<string>`(片段 ID) |
290
333
  | `removeClip(clipId)` | 移除片段 | `clipId`:片段 ID | 无 |
291
334
  | `removeSelectedClip()` | 移除当前选中的片段 | 无 | `boolean`(是否成功) |
@@ -15,10 +15,12 @@ export declare class Timeline {
15
15
  private onScrollChange;
16
16
  private animationFrameId;
17
17
  private isZooming;
18
+ private leftPadding;
18
19
  constructor(stage: Konva.Stage, gridLayer: Konva.Layer, config: Partial<TimelineConfig>, onTimeChange: (time: TimeMs) => void, onZoomChange: (zoom: number) => void, onScrollChange: (scrollLeft: number) => void);
19
20
  private initEventListeners;
20
21
  private handleZoom;
21
22
  private animateZoom;
23
+ private animateHorizontalScroll;
22
24
  private easeOutCubic;
23
25
  private handleClick;
24
26
  private pixelToTime;
@@ -33,6 +35,19 @@ export declare class Timeline {
33
35
  getConfig(): TimelineConfig;
34
36
  getScrollLeft(): number;
35
37
  setScrollLeft(scrollLeft: number): void;
38
+ /**
39
+ * 滚动到指定时间
40
+ * @param time 目标时间(毫秒)
41
+ */
42
+ scrollToTime(time: TimeMs): void;
43
+ /**
44
+ * 滚动到指定片段
45
+ * @param clip 目标片段
46
+ */
47
+ scrollToClip(clip: {
48
+ startTime: TimeMs;
49
+ duration: TimeMs;
50
+ }): void;
36
51
  /**
37
52
  * 获取舞台实例
38
53
  */
@@ -101,6 +101,11 @@ export declare class VideoTrack {
101
101
  render(): void;
102
102
  getClips(): ClipType[];
103
103
  getSelectedClip(): ClipType | null;
104
+ /**
105
+ * 选择指定的片段
106
+ * @param clipId 目标片段的 ID
107
+ */
108
+ selectClip(clipId: string): void;
104
109
  splitSelectedClip(time: TimeMs): void;
105
110
  /**
106
111
  * 删除轨道内片段之间的空隙
@@ -18,3 +18,4 @@ export declare const TIME_SCALE: {
18
18
  MIN_HEIGHT: number;
19
19
  MAX_HEIGHT: number;
20
20
  };
21
+ export declare const TIMELINE_LEFT_PADDING = 15;
@@ -1,4 +1,4 @@
1
- import { TimelineConfig, Clip, ClipConfig, TimeMs, PlayState, Action, TimelineEvent, EventListener, VideoPreviewConfig, TimelineExportData } from './types';
1
+ import { TimelineConfig, Clip, ClipConfig, TimeMs, PlayState, Action, TimelineEvent, EventListener, VideoPreviewConfig, TimelineExportData, ThumbnailProvider } from './types';
2
2
 
3
3
  export declare class TimelineManager {
4
4
  private timeline;
@@ -15,9 +15,11 @@ export declare class TimelineManager {
15
15
  private trackLayer;
16
16
  private playheadLayer;
17
17
  private selectionLayer;
18
+ private resizeObserver;
18
19
  private videoPreview;
19
20
  private isExecutingHistoryAction;
20
21
  private lastTrackDuration;
22
+ private thumbnailProvider;
21
23
  constructor(config?: Partial<TimelineConfig>);
22
24
  init(container: HTMLElement): void;
23
25
  play(): void;
@@ -38,9 +40,14 @@ export declare class TimelineManager {
38
40
  * @returns 当前播放倍速
39
41
  */
40
42
  getSpeed(): number;
43
+ /**
44
+ * 设置缩略图提供器
45
+ * @param provider 缩略图提供器
46
+ */
47
+ setThumbnailProvider(provider: ThumbnailProvider): void;
41
48
  addClip(clipConfig: ClipConfig): Promise<string>;
42
49
  removeClip(clipId: string): void;
43
- updateClip(clipId: string, updates: Partial<ClipConfig>): void;
50
+ updateClip(clipId: string, updates: Partial<Clip>): void;
44
51
  splitClip(clipId: string, time: TimeMs): void;
45
52
  splitCurrentClip(): void;
46
53
  getClips(): Clip[];
@@ -72,6 +79,32 @@ export declare class TimelineManager {
72
79
  getPlayState(): PlayState;
73
80
  setDuration(duration: TimeMs): void;
74
81
  getDuration(): TimeMs;
82
+ /**
83
+ * 调整时间轴大小以适配容器
84
+ * @param width 新的宽度
85
+ * @param height 新的高度
86
+ */
87
+ resize(width: number, height: number): void;
88
+ /**
89
+ * 滚动到指定时间
90
+ * @param time 目标时间(毫秒)
91
+ * @param setCurrentTime 是否同时将当前时间设置为该时间点,默认为 false
92
+ */
93
+ scrollToTime(time: TimeMs, setCurrentTime?: boolean): void;
94
+ /**
95
+ * 选择指定的片段
96
+ * @param clipId 目标片段的 ID
97
+ */
98
+ selectClip(clipId: string): void;
99
+ /**
100
+ * 滚动到指定片段
101
+ * @param clipId 目标片段的 ID
102
+ * @param options 配置选项
103
+ */
104
+ scrollToClip(clipId: string, options?: {
105
+ selectClip?: boolean;
106
+ setCurrentTime?: boolean;
107
+ }): void;
75
108
  /**
76
109
  * 获取当前时间点所在的clip
77
110
  * @returns 当前时间点所在的clip,如果没有则返回null
@@ -6,8 +6,17 @@ export interface LogConfig {
6
6
  level?: LogLevel;
7
7
  moduleLevels?: Record<string, LogLevel>;
8
8
  }
9
+ export interface ThumbnailProvider {
10
+ /**
11
+ * 获取片段的封面图片
12
+ * @param clip 片段对象
13
+ * @returns 封面图片URL、Promise<URL>或封面图片URL数组、Promise<URL数组>
14
+ */
15
+ getThumbnails(clip: Clip): string[] | Promise<string[]>;
16
+ }
9
17
  export interface ClipConfig {
10
18
  id?: string;
19
+ externalId?: string;
11
20
  src: string;
12
21
  name: string;
13
22
  startTime?: TimeMs;
@@ -15,11 +24,12 @@ export interface ClipConfig {
15
24
  startTimeAtSource?: TimeMs;
16
25
  endTimeAtSource?: TimeMs;
17
26
  sourceDuration?: TimeMs;
18
- thumbnail?: string;
27
+ thumbnails?: string[];
19
28
  style?: Record<string, any>;
20
29
  }
21
30
  export interface Clip {
22
31
  id: string;
32
+ externalId?: string;
23
33
  src: string;
24
34
  name: string;
25
35
  startTime: TimeMs;
@@ -35,7 +45,7 @@ export interface Clip {
35
45
  isSelected: boolean;
36
46
  zIndex: number;
37
47
  opacity: number;
38
- thumbnail?: string;
48
+ thumbnails?: string[];
39
49
  style?: Record<string, any>;
40
50
  }
41
51
  export interface TrackConfig {
@@ -57,11 +67,13 @@ export interface Theme {
57
67
  clipName: string;
58
68
  clipDuration: string;
59
69
  clipHandle: string;
70
+ clipCoverBackground: string;
60
71
  clipSelectedBackground: string;
61
72
  clipSelectedBorder: string;
62
73
  clipSelectedName: string;
63
74
  clipSelectedDuration: string;
64
75
  clipSelectedHandle: string;
76
+ clipSelectedCoverBackground: string;
65
77
  playhead: string;
66
78
  grid: string;
67
79
  }
@@ -76,6 +88,7 @@ export interface TimelineConfig {
76
88
  timeScaleHeight?: number;
77
89
  debug?: boolean;
78
90
  speed?: number;
91
+ thumbnailProvider?: ThumbnailProvider;
79
92
  }
80
93
  export interface VideoPreviewConfig {
81
94
  videoElement: HTMLVideoElement;
@@ -129,6 +142,7 @@ export interface TimelineManagerConfig {
129
142
  initialDuration?: TimeMs;
130
143
  initialZoom?: number;
131
144
  logConfig?: LogConfig;
145
+ thumbnailProvider?: ThumbnailProvider;
132
146
  }
133
147
  export interface TimelineExportData {
134
148
  version: string;
@@ -141,6 +155,7 @@ export interface TrackExportData {
141
155
  }
142
156
  export interface ClipExportData {
143
157
  id: string;
158
+ externalId?: string;
144
159
  src: string;
145
160
  name: string;
146
161
  startTime: TimeMs;
@@ -149,5 +164,5 @@ export interface ClipExportData {
149
164
  startTimeAtSource: TimeMs;
150
165
  endTimeAtSource: TimeMs;
151
166
  sourceDuration: TimeMs;
152
- thumbnail?: string;
167
+ thumbnails?: string[];
153
168
  }