@editframe/elements 0.15.0-beta.8 → 0.16.0-beta.0

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.
Files changed (52) hide show
  1. package/dist/EF_FRAMEGEN.d.ts +14 -10
  2. package/dist/EF_FRAMEGEN.js +17 -28
  3. package/dist/elements/EFCaptions.js +0 -7
  4. package/dist/elements/EFImage.js +0 -4
  5. package/dist/elements/EFMedia.d.ts +13 -7
  6. package/dist/elements/EFMedia.js +217 -111
  7. package/dist/elements/EFSourceMixin.js +2 -1
  8. package/dist/elements/EFTemporal.browsertest.d.ts +4 -3
  9. package/dist/elements/EFTemporal.d.ts +14 -11
  10. package/dist/elements/EFTemporal.js +63 -87
  11. package/dist/elements/EFTimegroup.d.ts +2 -4
  12. package/dist/elements/EFTimegroup.js +15 -103
  13. package/dist/elements/EFVideo.js +3 -1
  14. package/dist/elements/EFWaveform.d.ts +3 -2
  15. package/dist/elements/EFWaveform.js +39 -26
  16. package/dist/elements/durationConverter.d.ts +8 -8
  17. package/dist/elements/durationConverter.js +2 -2
  18. package/dist/elements/updateAnimations.d.ts +9 -0
  19. package/dist/elements/updateAnimations.js +62 -0
  20. package/dist/getRenderInfo.d.ts +51 -0
  21. package/dist/getRenderInfo.js +72 -0
  22. package/dist/gui/EFFilmstrip.js +7 -16
  23. package/dist/gui/EFFitScale.d.ts +27 -0
  24. package/dist/gui/EFFitScale.js +138 -0
  25. package/dist/gui/EFWorkbench.d.ts +2 -5
  26. package/dist/gui/EFWorkbench.js +13 -56
  27. package/dist/gui/TWMixin.css.js +1 -1
  28. package/dist/gui/TWMixin.js +14 -2
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.js +6 -1
  31. package/dist/style.css +6 -3
  32. package/package.json +9 -4
  33. package/src/elements/EFCaptions.browsertest.ts +2 -2
  34. package/src/elements/EFCaptions.ts +0 -7
  35. package/src/elements/EFImage.browsertest.ts +2 -2
  36. package/src/elements/EFImage.ts +0 -4
  37. package/src/elements/EFMedia.browsertest.ts +14 -14
  38. package/src/elements/EFMedia.ts +291 -136
  39. package/src/elements/EFSourceMixin.ts +4 -4
  40. package/src/elements/EFTemporal.browsertest.ts +64 -31
  41. package/src/elements/EFTemporal.ts +99 -119
  42. package/src/elements/EFTimegroup.ts +15 -133
  43. package/src/elements/EFVideo.ts +3 -1
  44. package/src/elements/EFWaveform.ts +54 -39
  45. package/src/elements/durationConverter.ts +9 -4
  46. package/src/elements/updateAnimations.ts +88 -0
  47. package/src/gui/ContextMixin.ts +0 -3
  48. package/src/gui/EFFilmstrip.ts +7 -16
  49. package/src/gui/EFFitScale.ts +152 -0
  50. package/src/gui/EFWorkbench.ts +18 -65
  51. package/src/gui/TWMixin.ts +19 -2
  52. package/types.json +1 -1
@@ -76,8 +76,10 @@ const EFTemporal = (superClass) => {
76
76
  constructor() {
77
77
  super(...arguments);
78
78
  this._offsetMs = 0;
79
- this._trimStartMs = 0;
80
- this._trimEndMs = 0;
79
+ this._trimStartMs = void 0;
80
+ this._trimEndMs = void 0;
81
+ this._sourceInMs = void 0;
82
+ this._sourceOutMs = void 0;
81
83
  this._startOffsetMs = 0;
82
84
  this.rootTimegroup = this.getRootTimegroup();
83
85
  this.frameTask = new Task(this, {
@@ -118,75 +120,46 @@ const EFTemporal = (superClass) => {
118
120
  }
119
121
  }
120
122
  get trimStartMs() {
121
- return this._trimStartMs;
122
- }
123
- set trimStartMs(value) {
124
- if (this._trimStartMs === value) {
125
- return;
123
+ if (this._trimStartMs === void 0) {
124
+ return void 0;
126
125
  }
127
- this._trimStartMs = value;
128
- this.setAttribute(
129
- "trimstart",
130
- durationConverter.toAttribute(value / 1e3)
126
+ return Math.min(
127
+ Math.max(this._trimStartMs, 0),
128
+ this.intrinsicDurationMs ?? 0
131
129
  );
132
130
  }
133
- set trimstart(value) {
134
- if (value !== void 0) {
135
- this.setAttribute("trimstart", value);
136
- } else {
137
- this.removeAttribute("trimstart");
138
- }
131
+ set trimStartMs(value) {
132
+ this._trimStartMs = value;
139
133
  }
140
134
  get trimEndMs() {
141
- return this._trimEndMs;
135
+ if (this._trimEndMs === void 0) {
136
+ return void 0;
137
+ }
138
+ return Math.min(this._trimEndMs, this.intrinsicDurationMs ?? 0);
142
139
  }
143
140
  set trimEndMs(value) {
144
- if (this._trimEndMs === value) {
145
- return;
146
- }
147
141
  this._trimEndMs = value;
148
- this.setAttribute("trimend", durationConverter.toAttribute(value / 1e3));
149
- }
150
- set trimend(value) {
151
- if (value !== void 0) {
152
- this.setAttribute("trimend", value);
153
- } else {
154
- this.removeAttribute("trimend");
155
- }
156
142
  }
157
143
  get sourceInMs() {
158
- return this._sourceInMs;
144
+ if (this._sourceInMs === void 0) {
145
+ return void 0;
146
+ }
147
+ return Math.max(this._sourceInMs, 0);
159
148
  }
160
149
  set sourceInMs(value) {
161
150
  this._sourceInMs = value;
162
- value !== void 0 ? this.setAttribute(
163
- "sourcein",
164
- durationConverter.toAttribute(value / 1e3)
165
- ) : this.removeAttribute("sourcein");
166
- }
167
- set sourcein(value) {
168
- if (value !== void 0) {
169
- this.setAttribute("sourcein", value);
170
- } else {
171
- this.removeAttribute("sourcein");
172
- }
173
151
  }
174
152
  get sourceOutMs() {
175
- return this._sourceOutMs;
153
+ if (this._sourceOutMs === void 0) {
154
+ return void 0;
155
+ }
156
+ if (this.intrinsicDurationMs && this._sourceOutMs > this.intrinsicDurationMs) {
157
+ return this.intrinsicDurationMs;
158
+ }
159
+ return Math.max(this._sourceOutMs, 0);
176
160
  }
177
161
  set sourceOutMs(value) {
178
162
  this._sourceOutMs = value;
179
- value !== void 0 ? this.setAttribute(
180
- "sourceout",
181
- durationConverter.toAttribute(value / 1e3)
182
- ) : this.removeAttribute("sourceout");
183
- }
184
- set sourceout(value) {
185
- if (value !== void 0) {
186
- this.setAttribute("sourceout", value);
187
- } else {
188
- this.removeAttribute("sourceout");
189
- }
190
163
  }
191
164
  get startOffsetMs() {
192
165
  return this._startOffsetMs;
@@ -201,19 +174,41 @@ const EFTemporal = (superClass) => {
201
174
  get hasExplicitDuration() {
202
175
  return this._durationMs !== void 0;
203
176
  }
177
+ get explicitDurationMs() {
178
+ if (this.hasExplicitDuration) {
179
+ return this._durationMs;
180
+ }
181
+ return void 0;
182
+ }
204
183
  get hasOwnDuration() {
205
184
  return false;
206
185
  }
207
- // Defining this as a getter to a private property allows us to
208
- // override it classes that include this mixin.
186
+ get intrinsicDurationMs() {
187
+ return void 0;
188
+ }
209
189
  get durationMs() {
210
- if (this.sourceInMs) {
211
- return this._durationMs || this.parentTimegroup?.durationMs || 0 - this.sourceInMs;
190
+ if (this.intrinsicDurationMs === void 0) {
191
+ return this._durationMs || this.parentTimegroup?.durationMs || 0;
212
192
  }
213
- if (this.sourceOutMs) {
214
- return this._durationMs || this.parentTimegroup?.durationMs || 0 - this.sourceOutMs;
193
+ if (this.trimStartMs || this.trimEndMs) {
194
+ const trimmedDurationMs = this.intrinsicDurationMs - (this.trimStartMs ?? 0) - (this.trimEndMs ?? 0);
195
+ if (trimmedDurationMs < 0) {
196
+ return 0;
197
+ }
198
+ return trimmedDurationMs;
199
+ }
200
+ if (this.sourceInMs || this.sourceOutMs) {
201
+ const sourceInMs = this.sourceInMs ?? 0;
202
+ const sourceOutMs = this.sourceOutMs ?? this.intrinsicDurationMs;
203
+ if (sourceInMs >= sourceOutMs) {
204
+ return 0;
205
+ }
206
+ return sourceOutMs - sourceInMs;
215
207
  }
216
- return this._durationMs || this.parentTimegroup?.durationMs || 0;
208
+ return this.intrinsicDurationMs;
209
+ }
210
+ get sourceStartMs() {
211
+ return this.trimStartMs ?? this.sourceInMs ?? 0;
217
212
  }
218
213
  get offsetMs() {
219
214
  return this._offsetMs || 0;
@@ -296,25 +291,8 @@ const EFTemporal = (superClass) => {
296
291
  * for mapping to internal media time codes for audio/video elements.
297
292
  */
298
293
  get currentSourceTimeMs() {
299
- if (this.rootTimegroup) {
300
- if (this.sourceInMs && this.sourceOutMs) {
301
- return Math.min(
302
- Math.max(
303
- 0,
304
- this.rootTimegroup.currentTimeMs - this.startTimeMs + this.trimStartMs + this.sourceInMs
305
- ),
306
- this.durationMs + Math.abs(this.startOffsetMs) + this.trimStartMs + this.sourceInMs
307
- );
308
- }
309
- return Math.min(
310
- Math.max(
311
- 0,
312
- this.rootTimegroup.currentTimeMs - this.startTimeMs + this.trimStartMs
313
- ),
314
- this.durationMs + Math.abs(this.startOffsetMs) + this.trimStartMs
315
- );
316
- }
317
- return 0;
294
+ const leadingTrimMs = this.sourceInMs || this.trimStartMs || 0;
295
+ return this.ownCurrentTimeMs + leadingTrimMs;
318
296
  }
319
297
  updated(changedProperties) {
320
298
  super.updated(changedProperties);
@@ -352,30 +330,28 @@ const EFTemporal = (superClass) => {
352
330
  attribute: "trimstart",
353
331
  converter: durationConverter
354
332
  })
355
- ], TemporalMixinClass.prototype, "trimStartMs", 1);
333
+ ], TemporalMixinClass.prototype, "_trimStartMs", 2);
356
334
  __decorateClass([
357
335
  property({
358
336
  type: Number,
359
337
  attribute: "trimend",
360
338
  converter: durationConverter
361
339
  })
362
- ], TemporalMixinClass.prototype, "trimEndMs", 1);
340
+ ], TemporalMixinClass.prototype, "_trimEndMs", 2);
363
341
  __decorateClass([
364
342
  property({
365
343
  type: Number,
366
344
  attribute: "sourcein",
367
- converter: durationConverter,
368
- reflect: true
345
+ converter: durationConverter
369
346
  })
370
- ], TemporalMixinClass.prototype, "sourceInMs", 1);
347
+ ], TemporalMixinClass.prototype, "_sourceInMs", 2);
371
348
  __decorateClass([
372
349
  property({
373
350
  type: Number,
374
351
  attribute: "sourceout",
375
- converter: durationConverter,
376
- reflect: true
352
+ converter: durationConverter
377
353
  })
378
- ], TemporalMixinClass.prototype, "sourceOutMs", 1);
354
+ ], TemporalMixinClass.prototype, "_sourceOutMs", 2);
379
355
  __decorateClass([
380
356
  property({
381
357
  type: Number,
@@ -17,9 +17,8 @@ export declare class EFTimegroup extends EFTimegroup_base {
17
17
  maybeLoadTimeFromLocalStorage(): number;
18
18
  connectedCallback(): void;
19
19
  disconnectedCallback(): void;
20
- private get displayedParent();
21
- private updateScale;
22
20
  get storageKey(): string;
21
+ get intrinsicDurationMs(): number | undefined;
23
22
  get durationMs(): number;
24
23
  /**
25
24
  * Wait for all media elements to load their initial segments.
@@ -27,7 +26,7 @@ export declare class EFTimegroup extends EFTimegroup_base {
27
26
  * that caused issues with constructing audio data. We had negative durations
28
27
  * in calculations and it was not clear why.
29
28
  */
30
- waitForMediaDurations(): Promise<Record<number, import('../../../assets/src/index.ts').TrackFragmentIndex>[]>;
29
+ waitForMediaDurations(): Promise<(Record<number, import('../../../assets/src/index.ts').TrackFragmentIndex> | undefined)[]>;
31
30
  get childTemporals(): import('./EFTemporal.js').TemporalMixinInterface[];
32
31
  protected updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
33
32
  private updateAnimations;
@@ -43,7 +42,6 @@ export declare class EFTimegroup extends EFTimegroup_base {
43
42
  */
44
43
  shouldWrapWithWorkbench(): boolean;
45
44
  wrapWithWorkbench(): void;
46
- get hasOwnDuration(): boolean;
47
45
  get efElements(): Element[];
48
46
  renderAudio(fromMs: number, toMs: number): Promise<AudioBuffer>;
49
47
  loadMd5Sums(): Promise<void>;
@@ -6,9 +6,10 @@ import { property, customElement } from "lit/decorators.js";
6
6
  import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
7
7
  import { isContextMixin } from "../gui/ContextMixin.js";
8
8
  import { deepGetMediaElements } from "./EFMedia.js";
9
- import { EFTemporal, shallowGetTemporalElements, isEFTemporal, timegroupContext } from "./EFTemporal.js";
9
+ import { EFTemporal, shallowGetTemporalElements, timegroupContext } from "./EFTemporal.js";
10
10
  import { TimegroupController } from "./TimegroupController.js";
11
11
  import { durationConverter } from "./durationConverter.js";
12
+ import { updateAnimations } from "./updateAnimations.js";
12
13
  var __defProp = Object.defineProperty;
13
14
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
14
15
  var __typeError = (msg) => {
@@ -107,51 +108,26 @@ let EFTimegroup = class extends EFTemporal(LitElement) {
107
108
  if (this.shouldWrapWithWorkbench()) {
108
109
  this.wrapWithWorkbench();
109
110
  }
110
- __privateSet(this, _resizeObserver, new ResizeObserver(() => this.updateScale()));
111
- if (this.parentElement) {
112
- __privateGet(this, _resizeObserver).observe(this.parentElement);
113
- }
114
- this.updateScale();
115
- requestAnimationFrame(() => this.updateAnimations());
111
+ requestAnimationFrame(() => {
112
+ this.updateAnimations();
113
+ });
116
114
  }
117
115
  disconnectedCallback() {
118
116
  super.disconnectedCallback();
119
117
  __privateGet(this, _resizeObserver)?.disconnect();
120
118
  }
121
- get displayedParent() {
122
- let displayedParent = this.parentElement;
123
- while (displayedParent && getComputedStyle(displayedParent).display === "contents") {
124
- displayedParent = displayedParent.parentElement;
125
- }
126
- return displayedParent;
127
- }
128
- updateScale() {
129
- if (this.fit === "none") return;
130
- const displayedParent = this.displayedParent;
131
- if (!displayedParent) return;
132
- const contentWidth = this.clientWidth;
133
- const contentHeight = this.clientHeight;
134
- const containerWidth = displayedParent.clientWidth;
135
- const containerHeight = displayedParent.clientHeight;
136
- const widthRatio = containerWidth / contentWidth;
137
- const heightRatio = containerHeight / contentHeight;
138
- let scale;
139
- if (this.fit === "contain") {
140
- scale = heightRatio;
141
- if (contentWidth * scale > containerWidth) {
142
- scale = widthRatio;
143
- }
144
- } else {
145
- scale = Math.max(widthRatio, heightRatio);
146
- }
147
- this.style.transform = `scale(${scale})`;
148
- }
149
119
  get storageKey() {
150
120
  if (!this.id) {
151
121
  throw new Error("Timegroup must have an id to use localStorage.");
152
122
  }
153
123
  return `ef-timegroup-${this.id}`;
154
124
  }
125
+ get intrinsicDurationMs() {
126
+ if (this.hasExplicitDuration) {
127
+ return this.explicitDurationMs;
128
+ }
129
+ return void 0;
130
+ }
155
131
  get durationMs() {
156
132
  switch (this.mode) {
157
133
  case "fixed":
@@ -169,7 +145,7 @@ let EFTimegroup = class extends EFTemporal(LitElement) {
169
145
  case "contain": {
170
146
  let maxDuration = 0;
171
147
  for (const node of this.childTemporals) {
172
- if (node.hasOwnDuration) {
148
+ if (node.intrinsicDurationMs !== void 0) {
173
149
  maxDuration = Math.max(maxDuration, node.durationMs);
174
150
  }
175
151
  }
@@ -201,69 +177,7 @@ let EFTimegroup = class extends EFTemporal(LitElement) {
201
177
  }
202
178
  }
203
179
  updateAnimations() {
204
- this.style.setProperty(
205
- "--ef-progress",
206
- `${Math.max(0, Math.min(1, this.currentTimeMs / this.durationMs)) * 100}%`
207
- );
208
- const timelineTimeMs = (this.rootTimegroup ?? this).currentTimeMs;
209
- if (this.startTimeMs > timelineTimeMs || this.endTimeMs < timelineTimeMs) {
210
- this.style.display = "none";
211
- return;
212
- }
213
- this.style.display = "";
214
- const animations = this.getAnimations({ subtree: true });
215
- this.style.setProperty("--ef-duration", `${this.durationMs}ms`);
216
- this.style.setProperty(
217
- "--ef-transition-duration",
218
- `${this.parentTimegroup?.overlapMs ?? 0}ms`
219
- );
220
- this.style.setProperty(
221
- "--ef-transition-out-start",
222
- `${this.durationMs - (this.parentTimegroup?.overlapMs ?? 0)}ms`
223
- );
224
- for (const animation of animations) {
225
- if (animation.playState === "running") {
226
- animation.pause();
227
- }
228
- const effect = animation.effect;
229
- if (!(effect && effect instanceof KeyframeEffect)) {
230
- return;
231
- }
232
- const target = effect.target;
233
- if (!target) {
234
- return;
235
- }
236
- if (target.closest("ef-timegroup") !== this) {
237
- return;
238
- }
239
- if (isEFTemporal(target)) {
240
- const timing = effect.getTiming();
241
- const duration = Number(timing.duration) ?? 0;
242
- const delay = Number(timing.delay);
243
- const newTime = Math.floor(
244
- Math.min(target.ownCurrentTimeMs, duration - 1 + delay)
245
- );
246
- if (Number.isNaN(newTime)) {
247
- return;
248
- }
249
- animation.currentTime = newTime;
250
- } else if (target) {
251
- const nearestTimegroup = target.closest("ef-timegroup");
252
- if (!nearestTimegroup) {
253
- return;
254
- }
255
- const timing = effect.getTiming();
256
- const duration = Number(timing.duration) ?? 0;
257
- const delay = Number(timing.delay);
258
- const newTime = Math.floor(
259
- Math.min(nearestTimegroup.ownCurrentTimeMs, duration - 1 + delay)
260
- );
261
- if (Number.isNaN(newTime)) {
262
- return;
263
- }
264
- animation.currentTime = newTime;
265
- }
266
- }
180
+ updateAnimations(this);
267
181
  }
268
182
  get contextProvider() {
269
183
  let parent = this.parentNode;
@@ -300,9 +214,6 @@ let EFTimegroup = class extends EFTemporal(LitElement) {
300
214
  filmstrip.setAttribute("target", this.id);
301
215
  workbench.append(filmstrip);
302
216
  }
303
- get hasOwnDuration() {
304
- return true;
305
- }
306
217
  get efElements() {
307
218
  return Array.from(
308
219
  this.querySelectorAll(
@@ -378,7 +289,8 @@ EFTimegroup.styles = css`
378
289
  width: 100%;
379
290
  height: 100%;
380
291
  position: absolute;
381
- transform-origin: center center;
292
+ top: 0;
293
+ left: 0;
382
294
  }
383
295
  `;
384
296
  __decorateClass([
@@ -93,7 +93,9 @@ let EFVideo = class extends TWMixin(EFMedia) {
93
93
  });
94
94
  }
95
95
  render() {
96
- return html` <canvas ${ref(this.canvasRef)}></canvas>`;
96
+ return html`
97
+ <canvas ${ref(this.canvasRef)}></canvas>
98
+ `;
97
99
  }
98
100
  get canvasElement() {
99
101
  return this.canvasRef.value;
@@ -13,9 +13,10 @@ export declare class EFWaveform extends EFWaveform_base {
13
13
  private resizeObserver?;
14
14
  private mutationObserver?;
15
15
  render(): import('lit-html').TemplateResult<1>;
16
- mode: "roundBars" | "bars" | "bricks" | "line" | "pixel" | "wave" | "spikes";
16
+ mode: "roundBars" | "bars" | "bricks" | "line" | "curve" | "pixel" | "wave" | "spikes";
17
17
  color: string;
18
18
  target: string;
19
+ barSpacing: number;
19
20
  targetElement: EFAudio | EFVideo | null;
20
21
  lineWidth: number;
21
22
  targetController: TargetController;
@@ -26,8 +27,8 @@ export declare class EFWaveform extends EFWaveform_base {
26
27
  protected drawBars(ctx: CanvasRenderingContext2D, frequencyData: Uint8Array): void;
27
28
  protected drawBricks(ctx: CanvasRenderingContext2D, frequencyData: Uint8Array): void;
28
29
  protected drawRoundBars(ctx: CanvasRenderingContext2D, frequencyData: Uint8Array): void;
29
- protected drawEqualizer(ctx: CanvasRenderingContext2D, frequencyData: Uint8Array): void;
30
30
  protected drawLine(ctx: CanvasRenderingContext2D, frequencyData: Uint8Array): void;
31
+ protected drawCurve(ctx: CanvasRenderingContext2D, frequencyData: Uint8Array): void;
31
32
  protected drawPixel(ctx: CanvasRenderingContext2D, frequencyData: Uint8Array): void;
32
33
  protected drawWave(ctx: CanvasRenderingContext2D, frequencyData: Uint8Array): void;
33
34
  protected drawSpikes(ctx: CanvasRenderingContext2D, frequencyData: Uint8Array): void;
@@ -28,6 +28,7 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
28
28
  this.mode = "bars";
29
29
  this.color = "currentColor";
30
30
  this.target = "";
31
+ this.barSpacing = 0.5;
31
32
  this.targetElement = null;
32
33
  this.lineWidth = 4;
33
34
  this.targetController = new TargetController(this);
@@ -46,7 +47,8 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
46
47
  const ctx = this.ctx;
47
48
  if (!ctx) return;
48
49
  const frequencyData = this.targetElement.frequencyDataTask.value;
49
- if (!frequencyData) return;
50
+ const byteTimeData = this.targetElement.byteTimeDomainTask.value;
51
+ if (!frequencyData || !byteTimeData) return;
50
52
  ctx.save();
51
53
  if (this.color === "currentColor") {
52
54
  const computedStyle = getComputedStyle(this);
@@ -65,7 +67,10 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
65
67
  this.drawBricks(ctx, frequencyData);
66
68
  break;
67
69
  case "line":
68
- this.drawLine(ctx, frequencyData);
70
+ this.drawLine(ctx, byteTimeData);
71
+ break;
72
+ case "curve":
73
+ this.drawCurve(ctx, byteTimeData);
69
74
  break;
70
75
  case "pixel":
71
76
  this.drawPixel(ctx, frequencyData);
@@ -148,14 +153,14 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
148
153
  const waveWidth = canvas.width;
149
154
  const waveHeight = canvas.height;
150
155
  const totalBars = frequencyData.length;
151
- const paddingInner = 0.5;
156
+ const paddingInner = this.barSpacing;
152
157
  const paddingOuter = 0.01;
153
158
  const availableWidth = waveWidth;
154
159
  const barWidth = availableWidth / (totalBars + (totalBars - 1) * paddingInner);
155
160
  ctx.clearRect(0, 0, waveWidth, waveHeight);
156
161
  const path = new Path2D();
157
162
  frequencyData.forEach((value, i) => {
158
- const normalizedValue = Math.min(value / 255 * 2, 1);
163
+ const normalizedValue = value / 255;
159
164
  const barHeight = normalizedValue * waveHeight;
160
165
  const y = (waveHeight - barHeight) / 2;
161
166
  const x = waveWidth * paddingOuter + i * (barWidth * (1 + paddingInner));
@@ -174,7 +179,7 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
174
179
  const verticalGap = boxSize * 0.2;
175
180
  const maxBricks = Math.floor(waveHeight / (boxSize + verticalGap));
176
181
  frequencyData.forEach((value, i) => {
177
- const normalizedValue = Math.min(value / 255 * 2, 1);
182
+ const normalizedValue = value / 255;
178
183
  const brickCount = Math.floor(normalizedValue * maxBricks);
179
184
  for (let j = 0; j < brickCount; j++) {
180
185
  const x = columnWidth * i;
@@ -189,14 +194,14 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
189
194
  const waveWidth = canvas.width;
190
195
  const waveHeight = canvas.height;
191
196
  const totalBars = frequencyData.length;
192
- const paddingInner = 0.5;
197
+ const paddingInner = this.barSpacing;
193
198
  const paddingOuter = 0.01;
194
199
  const availableWidth = waveWidth;
195
200
  const barWidth = availableWidth / (totalBars + (totalBars - 1) * paddingInner);
196
201
  ctx.clearRect(0, 0, waveWidth, waveHeight);
197
202
  const path = new Path2D();
198
203
  frequencyData.forEach((value, i) => {
199
- const normalizedValue = Math.min(value / 255 * 2, 1);
204
+ const normalizedValue = value / 255;
200
205
  const height = normalizedValue * waveHeight;
201
206
  const x = waveWidth * paddingOuter + i * (barWidth * (1 + paddingInner));
202
207
  const y = (waveHeight - height) / 2;
@@ -204,28 +209,29 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
204
209
  });
205
210
  ctx.fill(path);
206
211
  }
207
- drawEqualizer(ctx, frequencyData) {
212
+ drawLine(ctx, frequencyData) {
208
213
  const canvas = ctx.canvas;
209
214
  const waveWidth = canvas.width;
210
215
  const waveHeight = canvas.height;
211
- const baseline = waveHeight / 2;
212
- const barWidth = waveWidth / frequencyData.length * 0.8;
213
216
  ctx.clearRect(0, 0, waveWidth, waveHeight);
214
- const baselinePath = new Path2D();
215
- const barsPath = new Path2D();
216
- baselinePath.moveTo(0, baseline);
217
- baselinePath.lineTo(waveWidth, baseline);
218
- frequencyData.forEach((value, i) => {
219
- const height = value / 255 * (waveHeight / 2);
220
- const x = i * (waveWidth / frequencyData.length);
221
- const y = baseline - height;
222
- barsPath.rect(x, y, barWidth, Math.max(height * 2, 1));
223
- });
224
- ctx.lineWidth = 2;
225
- ctx.stroke(baselinePath);
226
- ctx.fill(barsPath);
217
+ const path = new Path2D();
218
+ const sampleRate = 1;
219
+ for (let i = 0; i < frequencyData.length; i += sampleRate) {
220
+ const x = i / frequencyData.length * waveWidth;
221
+ const y = (1 - (frequencyData[i] ?? 0) / 255) * waveHeight;
222
+ if (i === 0) {
223
+ path.moveTo(x, y);
224
+ } else {
225
+ path.lineTo(x, y);
226
+ }
227
+ }
228
+ const lastX = waveWidth;
229
+ const lastY = (1 - (frequencyData[frequencyData.length - 1] ?? 0) / 255) * waveHeight;
230
+ path.lineTo(lastX, lastY);
231
+ ctx.lineWidth = this.lineWidth;
232
+ ctx.stroke(path);
227
233
  }
228
- drawLine(ctx, frequencyData) {
234
+ drawCurve(ctx, frequencyData) {
229
235
  const canvas = ctx.canvas;
230
236
  const waveWidth = canvas.width;
231
237
  const waveHeight = canvas.height;
@@ -237,7 +243,11 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
237
243
  if (i === 0) {
238
244
  path.moveTo(x, y);
239
245
  } else {
240
- path.lineTo(x, y);
246
+ const prevX = (i - 1) / frequencyData.length * waveWidth;
247
+ const prevY = (1 - (frequencyData[i - 1] ?? 0) / 255) * waveHeight;
248
+ const xc = (prevX + x) / 2;
249
+ const yc = (prevY + y) / 2;
250
+ path.quadraticCurveTo(prevX, prevY, xc, yc);
241
251
  }
242
252
  });
243
253
  ctx.lineWidth = this.lineWidth;
@@ -252,7 +262,7 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
252
262
  ctx.clearRect(0, 0, waveWidth, waveHeight);
253
263
  const path = new Path2D();
254
264
  frequencyData.forEach((value, i) => {
255
- const normalizedValue = Math.min(value / 255 * 2, 1);
265
+ const normalizedValue = value / 255;
256
266
  const x = i * (waveWidth / frequencyData.length);
257
267
  const barHeight = normalizedValue * (waveHeight / 2);
258
268
  const y = baseline - barHeight;
@@ -402,6 +412,9 @@ __decorateClass([
402
412
  __decorateClass([
403
413
  property({ type: String, reflect: true })
404
414
  ], EFWaveform.prototype, "target", 2);
415
+ __decorateClass([
416
+ property({ type: Number, attribute: "bar-spacing" })
417
+ ], EFWaveform.prototype, "barSpacing", 2);
405
418
  __decorateClass([
406
419
  state()
407
420
  ], EFWaveform.prototype, "targetElement", 2);
@@ -1,16 +1,16 @@
1
1
  export declare const durationConverter: {
2
- fromAttribute: (value: string) => number;
3
- toAttribute: (value: number) => string;
2
+ fromAttribute: (value: string | null) => number | null;
3
+ toAttribute: (value: number | null) => string | null;
4
4
  };
5
5
  export declare const trimDurationConverter: {
6
- fromAttribute: (value: string) => number;
7
- toAttribute: (value: number) => string;
6
+ fromAttribute: (value: string | null) => number | null;
7
+ toAttribute: (value: number | null) => string | null;
8
8
  };
9
9
  export declare const imageDurationConverter: {
10
- fromAttribute: (value: string) => number;
11
- toAttribute: (value: number) => string;
10
+ fromAttribute: (value: string | null) => number | null;
11
+ toAttribute: (value: number | null) => string | null;
12
12
  };
13
13
  export declare const sourceDurationConverter: {
14
- fromAttribute: (value: string) => number;
15
- toAttribute: (value: number) => string;
14
+ fromAttribute: (value: string | null) => number | null;
15
+ toAttribute: (value: number | null) => string | null;
16
16
  };
@@ -1,7 +1,7 @@
1
1
  import { parseTimeToMs } from "./parseTimeToMs.js";
2
2
  const durationConverter = {
3
- fromAttribute: (value) => parseTimeToMs(value),
4
- toAttribute: (value) => `${value}s`
3
+ fromAttribute: (value) => value === null ? null : parseTimeToMs(value),
4
+ toAttribute: (value) => value === null ? null : `${value}s`
5
5
  };
6
6
  export {
7
7
  durationConverter
@@ -0,0 +1,9 @@
1
+ import { EFTimegroup } from './EFTimegroup.ts';
2
+ export declare const updateAnimations: (element: HTMLElement & {
3
+ currentTimeMs: number;
4
+ durationMs: number;
5
+ rootTimegroup?: EFTimegroup;
6
+ parentTimegroup?: EFTimegroup;
7
+ startTimeMs: number;
8
+ endTimeMs: number;
9
+ }) => void;