@pixerate/editor-svelte 0.5.4 → 0.5.5
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/package.json
CHANGED
|
@@ -447,4 +447,146 @@ describe('createCanvasExplosion Rune Lifecycle & Reversibility', () => {
|
|
|
447
447
|
globalThis.requestAnimationFrame = originalRaf;
|
|
448
448
|
}
|
|
449
449
|
});
|
|
450
|
+
|
|
451
|
+
it('animates opacity for child nodes and connecting edges while preserving full opacity of displaced sibling nodes', () => {
|
|
452
|
+
let currentTime = 1000;
|
|
453
|
+
const originalDateNow = Date.now;
|
|
454
|
+
Date.now = () => currentTime;
|
|
455
|
+
|
|
456
|
+
let rafCallback: (() => void) | null = null;
|
|
457
|
+
const originalRaf = globalThis.requestAnimationFrame;
|
|
458
|
+
globalThis.requestAnimationFrame = ((cb: () => void) => {
|
|
459
|
+
rafCallback = cb;
|
|
460
|
+
return 1;
|
|
461
|
+
}) as any;
|
|
462
|
+
|
|
463
|
+
try {
|
|
464
|
+
const origin = createNode('origin', 200, 200);
|
|
465
|
+
const siblingAbove = createNode('above', 200, 100);
|
|
466
|
+
const siblingBelow = createNode('below', 200, 300);
|
|
467
|
+
|
|
468
|
+
const graph = createCanvasGraph({
|
|
469
|
+
initialNodes: [origin, siblingAbove, siblingBelow]
|
|
470
|
+
});
|
|
471
|
+
const explosion = createCanvasExplosion(graph);
|
|
472
|
+
|
|
473
|
+
const child = createNode('c1', 500, 200);
|
|
474
|
+
|
|
475
|
+
const forwardTrajectory = createFanOutTrajectory({
|
|
476
|
+
startOpacity: 0,
|
|
477
|
+
endOpacity: 1,
|
|
478
|
+
curvature: 0
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
const reverseTrajectory = createFanOutTrajectory({
|
|
482
|
+
startOpacity: 1,
|
|
483
|
+
endOpacity: 0,
|
|
484
|
+
curvature: 0
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
explosion.explodeNode('origin', {
|
|
488
|
+
childNodes: [child],
|
|
489
|
+
duration: 200,
|
|
490
|
+
easing: (t) => t,
|
|
491
|
+
trajectory: forwardTrajectory,
|
|
492
|
+
connectParentToChildren: 'all',
|
|
493
|
+
directionalOptions: { direction: 'vertical', gap: 20 }
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
// Frame 0: child node and edge start with opacity 0
|
|
497
|
+
let graphChild = graph.nodes.find((n) => n.id === 'c1')!;
|
|
498
|
+
let graphEdge = graph.edges.find((e) => e.source === 'origin' && e.target === 'c1')!;
|
|
499
|
+
let graphAbove = graph.nodes.find((n) => n.id === 'above')!;
|
|
500
|
+
let graphBelow = graph.nodes.find((n) => n.id === 'below')!;
|
|
501
|
+
|
|
502
|
+
expect(graphChild.style).toContain('opacity: 0');
|
|
503
|
+
expect(graphEdge.style).toContain('opacity: 0');
|
|
504
|
+
// Displaced siblings should never be faded
|
|
505
|
+
expect(graphAbove.style || '').not.toContain('opacity: 0');
|
|
506
|
+
expect(graphBelow.style || '').not.toContain('opacity: 0');
|
|
507
|
+
|
|
508
|
+
// Advance 100ms (50% progress)
|
|
509
|
+
currentTime = 1100;
|
|
510
|
+
if (rafCallback) {
|
|
511
|
+
const nextCb = rafCallback;
|
|
512
|
+
rafCallback = null;
|
|
513
|
+
nextCb();
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
graphChild = graph.nodes.find((n) => n.id === 'c1')!;
|
|
517
|
+
graphEdge = graph.edges.find((e) => e.source === 'origin' && e.target === 'c1')!;
|
|
518
|
+
graphAbove = graph.nodes.find((n) => n.id === 'above')!;
|
|
519
|
+
graphBelow = graph.nodes.find((n) => n.id === 'below')!;
|
|
520
|
+
|
|
521
|
+
expect(graphChild.position.x).toBeCloseTo(335, 0); // quadratic bezier curve at t=0.5
|
|
522
|
+
expect(graphChild.style).toContain('opacity: 0.5');
|
|
523
|
+
expect(graphEdge.style).toContain('opacity: 0.5');
|
|
524
|
+
// Displaced siblings move vertically without horizontal change and without opacity modification
|
|
525
|
+
expect(graphAbove.position.x).toBe(200);
|
|
526
|
+
expect(graphBelow.position.x).toBe(200);
|
|
527
|
+
expect(graphAbove.style || '').not.toContain('opacity: 0.5');
|
|
528
|
+
|
|
529
|
+
// Advance 100ms (100% progress)
|
|
530
|
+
currentTime = 1200;
|
|
531
|
+
if (rafCallback) {
|
|
532
|
+
const nextCb = rafCallback;
|
|
533
|
+
rafCallback = null;
|
|
534
|
+
nextCb();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
graphChild = graph.nodes.find((n) => n.id === 'c1')!;
|
|
538
|
+
graphEdge = graph.edges.find((e) => e.source === 'origin' && e.target === 'c1')!;
|
|
539
|
+
graphAbove = graph.nodes.find((n) => n.id === 'above')!;
|
|
540
|
+
graphBelow = graph.nodes.find((n) => n.id === 'below')!;
|
|
541
|
+
|
|
542
|
+
expect(graphChild.position.x).toBe(500);
|
|
543
|
+
expect(graphChild.style || '').not.toContain('opacity: 0');
|
|
544
|
+
expect((graphChild.data as any).opacity).toBe(1);
|
|
545
|
+
expect(graphAbove.position.y).toBeLessThan(100);
|
|
546
|
+
expect(graphBelow.position.y).toBeGreaterThan(300);
|
|
547
|
+
|
|
548
|
+
// Now collapse with reverse trajectory
|
|
549
|
+
explosion.collapseNode('origin', {
|
|
550
|
+
duration: 200,
|
|
551
|
+
easing: (t) => t,
|
|
552
|
+
trajectory: reverseTrajectory
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
// Advance 100ms into collapse (50%)
|
|
556
|
+
currentTime = 1300;
|
|
557
|
+
if (rafCallback) {
|
|
558
|
+
const nextCb = rafCallback;
|
|
559
|
+
rafCallback = null;
|
|
560
|
+
nextCb();
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
graphChild = graph.nodes.find((n) => n.id === 'c1')!;
|
|
564
|
+
graphEdge = graph.edges.find((e) => e.source === 'origin' && e.target === 'c1')!;
|
|
565
|
+
expect(graphChild.position.x).toBeCloseTo(365, 0); // quadratic bezier curve at t=0.5 on collapse
|
|
566
|
+
expect(graphChild.style).toContain('opacity: 0.5');
|
|
567
|
+
expect(graphEdge.style).toContain('opacity: 0.5');
|
|
568
|
+
|
|
569
|
+
// Advance 100ms (collapse completion)
|
|
570
|
+
currentTime = 1400;
|
|
571
|
+
if (rafCallback) {
|
|
572
|
+
const nextCb = rafCallback;
|
|
573
|
+
rafCallback = null;
|
|
574
|
+
nextCb();
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
expect(graph.nodes.some((n) => n.id === 'c1')).toBe(false);
|
|
578
|
+
expect(graph.edges.some((e) => e.source === 'origin' && e.target === 'c1')).toBe(false);
|
|
579
|
+
expect(explosion.isExploded('origin')).toBe(false);
|
|
580
|
+
|
|
581
|
+
graphAbove = graph.nodes.find((n) => n.id === 'above')!;
|
|
582
|
+
graphBelow = graph.nodes.find((n) => n.id === 'below')!;
|
|
583
|
+
expect(graphAbove.position.y).toBe(100);
|
|
584
|
+
expect(graphBelow.position.y).toBe(300);
|
|
585
|
+
expect(graphAbove.position.x).toBe(200);
|
|
586
|
+
expect(graphBelow.position.x).toBe(200);
|
|
587
|
+
} finally {
|
|
588
|
+
Date.now = originalDateNow;
|
|
589
|
+
globalThis.requestAnimationFrame = originalRaf;
|
|
590
|
+
}
|
|
591
|
+
});
|
|
450
592
|
});
|