@editframe/elements 0.15.0-beta.14 → 0.15.0-beta.15

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.
@@ -45,8 +45,15 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
45
45
  type: String,
46
46
  attribute: "mode",
47
47
  })
48
- mode: "roundBars" | "bars" | "bricks" | "line" | "curve" | "pixel" | "wave" =
49
- "bars";
48
+ mode:
49
+ | "roundBars"
50
+ | "bars"
51
+ | "bricks"
52
+ | "line"
53
+ | "curve"
54
+ | "pixel"
55
+ | "wave"
56
+ | "spikes" = "bars";
50
57
 
51
58
  @property({ type: String })
52
59
  color = "currentColor";
@@ -157,7 +164,7 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
157
164
  const path = new Path2D();
158
165
 
159
166
  frequencyData.forEach((value, i) => {
160
- const normalizedValue = Math.abs(value - 128) / 128;
167
+ const normalizedValue = value / 255;
161
168
  const barHeight = normalizedValue * waveHeight;
162
169
  const y = (waveHeight - barHeight) / 2;
163
170
  const x = waveWidth * paddingOuter + i * (barWidth * (1 + paddingInner));
@@ -183,7 +190,7 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
183
190
  const maxBricks = Math.floor(waveHeight / (boxSize + verticalGap)); // Account for gaps in height calculation
184
191
 
185
192
  frequencyData.forEach((value, i) => {
186
- const normalizedValue = Math.abs(value - 128) / 128;
193
+ const normalizedValue = value / 255;
187
194
  const brickCount = Math.floor(normalizedValue * maxBricks);
188
195
 
189
196
  for (let j = 0; j < brickCount; j++) {
@@ -218,7 +225,7 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
218
225
  const path = new Path2D();
219
226
 
220
227
  frequencyData.forEach((value, i) => {
221
- const normalizedValue = Math.abs(value - 128) / 128;
228
+ const normalizedValue = value / 255;
222
229
  const height = normalizedValue * waveHeight; // Use full wave height like in drawBars
223
230
  const x = waveWidth * paddingOuter + i * (barWidth * (1 + paddingInner));
224
231
  const y = (waveHeight - height) / 2; // Center vertically
@@ -307,7 +314,7 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
307
314
  const path = new Path2D();
308
315
 
309
316
  frequencyData.forEach((value, i) => {
310
- const normalizedValue = Math.abs(value - 128) / 128;
317
+ const normalizedValue = value / 255;
311
318
  const x = i * (waveWidth / frequencyData.length);
312
319
  const barHeight = normalizedValue * (waveHeight / 2); // Half height since we extend both ways
313
320
  const y = baseline - barHeight;
@@ -328,50 +335,129 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
328
335
  ctx.clearRect(0, 0, waveWidth, waveHeight);
329
336
  const path = new Path2D();
330
337
 
331
- // For PCM data, normalize around the center point (128)
332
- const firstValue = ((frequencyData[0] ?? 128) - 128) / 128;
333
- const firstY = waveHeight / 2 + (firstValue * waveHeight) / 2;
338
+ // Draw top curve
339
+ const firstValue = Math.min(((frequencyData[0] ?? 0) / 255) * 2, 1);
340
+ const firstY = (waveHeight - firstValue * waveHeight) / 2;
334
341
  path.moveTo(startX, firstY);
335
342
 
336
343
  // Draw top half
337
344
  frequencyData.forEach((value, i) => {
338
- const normalizedValue = (value - 128) / 128; // Center around 0 (-1 to 1)
345
+ const normalizedValue = Math.min((value / 255) * 2, 1);
339
346
  const x = startX + (i / (frequencyData.length - 1)) * availableWidth;
340
- const y = waveHeight / 2 - (normalizedValue * waveHeight) / 2; // Create downward curve for top
347
+ const barHeight = normalizedValue * waveHeight;
348
+ const y = (waveHeight - barHeight) / 2;
341
349
 
342
350
  if (i === 0) {
343
351
  path.moveTo(x, y);
344
352
  } else {
345
353
  const prevX =
346
354
  startX + ((i - 1) / (frequencyData.length - 1)) * availableWidth;
347
- const prevValue = ((frequencyData[i - 1] ?? 128) - 128) / 128;
348
- const prevY = waveHeight / 2 - (prevValue * waveHeight) / 2; // Create downward curve for top
355
+ const prevValue = Math.min(((frequencyData[i - 1] ?? 0) / 255) * 2, 1);
356
+ const prevBarHeight = prevValue * waveHeight;
357
+ const prevY = (waveHeight - prevBarHeight) / 2;
349
358
  const xc = (prevX + x) / 2;
350
- const yc = (prevY + y) / 2; // Control point for smooth curve
351
- path.quadraticCurveTo(prevX, prevY, xc, yc); // Maintain the curve
359
+ const yc = (prevY + y) / 2;
360
+ path.quadraticCurveTo(prevX, prevY, xc, yc);
352
361
  }
353
362
  });
354
363
 
355
- // Draw bottom mirror
364
+ // Draw bottom half
356
365
  for (let i = frequencyData.length - 1; i >= 0; i--) {
357
- const normalizedValue = ((frequencyData[i] ?? 128) - 128) / 128; // Center around 0 (-1 to 1)
366
+ const normalizedValue = Math.min(((frequencyData[i] ?? 0) / 255) * 2, 1);
358
367
  const x = startX + (i / (frequencyData.length - 1)) * availableWidth;
359
- const y = waveHeight / 2 + (normalizedValue * waveHeight) / 2; // Create upward curve for bottom
368
+ const barHeight = normalizedValue * waveHeight;
369
+ const y = (waveHeight + barHeight) / 2;
360
370
 
361
371
  if (i === frequencyData.length - 1) {
362
372
  path.lineTo(x, y);
363
373
  } else {
364
374
  const nextX =
365
375
  startX + ((i + 1) / (frequencyData.length - 1)) * availableWidth;
366
- const nextValue = ((frequencyData[i + 1] ?? 128) - 128) / 128;
367
- const nextY = waveHeight / 2 + (nextValue * waveHeight) / 2; // Create upward curve for bottom
376
+ const nextValue = Math.min(((frequencyData[i + 1] ?? 0) / 255) * 2, 1);
377
+ const nextBarHeight = nextValue * waveHeight;
378
+ const nextY = (waveHeight + nextBarHeight) / 2;
368
379
  const xc = (nextX + x) / 2;
369
- const yc = (nextY + y) / 2; // Control point for smooth curve
370
- path.quadraticCurveTo(nextX, nextY, xc, yc); // Maintain the curve
380
+ const yc = (nextY + y) / 2;
381
+ path.quadraticCurveTo(nextX, nextY, xc, yc);
371
382
  }
372
383
  }
373
384
 
374
- path.closePath();
385
+ // Close the path with a smooth curve back to start
386
+ const lastY = (waveHeight + firstValue * waveHeight) / 2;
387
+ const controlX = startX;
388
+ const controlY = (lastY + firstY) / 2;
389
+ path.quadraticCurveTo(controlX, controlY, startX, firstY);
390
+
391
+ ctx.fill(path);
392
+ }
393
+
394
+ protected drawSpikes(
395
+ ctx: CanvasRenderingContext2D,
396
+ frequencyData: Uint8Array,
397
+ ) {
398
+ const canvas = ctx.canvas;
399
+ const waveWidth = canvas.width;
400
+ const waveHeight = canvas.height;
401
+ const paddingOuter = 0.01;
402
+ const availableWidth = waveWidth * (1 - 2 * paddingOuter);
403
+ const startX = waveWidth * paddingOuter;
404
+
405
+ ctx.clearRect(0, 0, waveWidth, waveHeight);
406
+ const path = new Path2D();
407
+
408
+ // Draw top curve
409
+ const firstValue = (frequencyData[0] ?? 0) / 255;
410
+ const firstY = (waveHeight - firstValue * waveHeight) / 2;
411
+ path.moveTo(startX, firstY);
412
+
413
+ // Draw top half
414
+ frequencyData.forEach((value, i) => {
415
+ const normalizedValue = Math.min((value / 255) * 2, 1);
416
+ const x = startX + (i / (frequencyData.length - 1)) * availableWidth;
417
+ const barHeight = normalizedValue * (waveHeight / 2);
418
+ const y = (waveHeight - barHeight * 2) / 2;
419
+
420
+ if (i === 0) {
421
+ path.moveTo(x, y);
422
+ } else {
423
+ const prevX =
424
+ startX + ((i - 1) / (frequencyData.length - 1)) * availableWidth;
425
+ const prevValue = (frequencyData[i - 1] ?? 0) / 255;
426
+ const prevBarHeight = prevValue * (waveHeight / 2);
427
+ const prevY = (waveHeight - prevBarHeight * 2) / 2;
428
+ const xc = (prevX + x) / 2;
429
+ const yc = (prevY + y) / 2;
430
+ path.quadraticCurveTo(prevX, prevY, xc, yc);
431
+ }
432
+ });
433
+
434
+ // Draw bottom half
435
+ for (let i = frequencyData.length - 1; i >= 0; i--) {
436
+ const normalizedValue = Math.min(((frequencyData[i] ?? 0) / 255) * 2, 1);
437
+ const x = startX + (i / (frequencyData.length - 1)) * availableWidth;
438
+ const barHeight = normalizedValue * (waveHeight / 2);
439
+ const y = (waveHeight + barHeight * 2) / 2;
440
+
441
+ if (i === frequencyData.length - 1) {
442
+ path.lineTo(x, y);
443
+ } else {
444
+ const nextX =
445
+ startX + ((i + 1) / (frequencyData.length - 1)) * availableWidth;
446
+ const nextValue = (frequencyData[i + 1] ?? 0) / 255;
447
+ const nextBarHeight = nextValue * (waveHeight / 2);
448
+ const nextY = (waveHeight + nextBarHeight * 2) / 2;
449
+ const xc = (nextX + x) / 2;
450
+ const yc = (nextY + y) / 2;
451
+ path.quadraticCurveTo(nextX, nextY, xc, yc);
452
+ }
453
+ }
454
+
455
+ // Close the path with a smooth curve
456
+ const lastY = (waveHeight + firstValue * waveHeight) / 2;
457
+ const controlX = startX;
458
+ const controlY = (lastY + firstY) / 2;
459
+ path.quadraticCurveTo(controlX, controlY, startX, firstY);
460
+
375
461
  ctx.fill(path);
376
462
  }
377
463
 
@@ -407,10 +493,10 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
407
493
 
408
494
  switch (this.mode) {
409
495
  case "bars":
410
- this.drawBars(ctx, byteTimeData);
496
+ this.drawBars(ctx, frequencyData);
411
497
  break;
412
498
  case "bricks":
413
- this.drawBricks(ctx, byteTimeData);
499
+ this.drawBricks(ctx, frequencyData);
414
500
  break;
415
501
  case "line":
416
502
  this.drawLine(ctx, byteTimeData);
@@ -419,13 +505,16 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
419
505
  this.drawCurve(ctx, byteTimeData);
420
506
  break;
421
507
  case "pixel":
422
- this.drawPixel(ctx, byteTimeData);
508
+ this.drawPixel(ctx, frequencyData);
423
509
  break;
424
510
  case "wave":
425
- this.drawWave(ctx, byteTimeData);
511
+ this.drawWave(ctx, frequencyData);
512
+ break;
513
+ case "spikes":
514
+ this.drawSpikes(ctx, frequencyData);
426
515
  break;
427
516
  case "roundBars":
428
- this.drawRoundBars(ctx, byteTimeData);
517
+ this.drawRoundBars(ctx, frequencyData);
429
518
  break;
430
519
  }
431
520