cytoscape-canvas-underlay 1.2.4 → 1.3.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.
package/README.md CHANGED
@@ -8,7 +8,7 @@ A [Cytoscape.js](https://js.cytoscape.org) plugin for rendering image/PDF backgr
8
8
  - **Pan clamping** — hard boundary or iOS-style rubber-band with spring-back
9
9
  - **Minimap** — DOM-based crisp image rendering, two viewport styles (`dim` / `rect`), auto-hide, full customization
10
10
  - **Adaptive PDF quality** — low-quality render during interaction, high-quality on idle
11
- - **Rich navigation** — `fit`, `fitAll`, `panToElement`, `panToRegion`, coordinate conversion
11
+ - **Rich navigation** — `fit`, `fitAll`, `panToRegion`, coordinate conversion
12
12
  - **Layer visibility** — independently show/hide drawing background and graph layer
13
13
  - **CSS filters** — invert, brightness, contrast, saturate, grayscale (invert applied first so brightness/contrast work correctly on inverted images)
14
14
  - **Rotation** — rotate main or additional drawings (0, 90, 180, 270 degrees)
@@ -147,13 +147,14 @@ api.off('zoom'); // remove all zoom handlers
147
147
  ### Navigation
148
148
 
149
149
  ```js
150
- api.fit(); // fit main drawing
150
+ api.fit(); // fit main drawing (instant)
151
+ api.fit({ animate: true }); // fit with animation (300ms)
152
+ api.fit({ padding: 50 }); // fit with 50px padding
153
+ api.fit({ animate: true, duration: 500, easing: 'ease-out' });
151
154
  api.fitToDrawing('trace-1'); // fit specific drawing
152
155
  api.fitAll(); // fit all drawings
153
156
  api.panTo(500, 300); // center on world coordinate
154
157
  api.panTo(500, 300, 2.0); // center + set zoom
155
- api.panToElement('node-id'); // center on cytoscape element
156
- api.panToElement(cy.$('#node-id')); // also accepts element reference
157
158
  api.panToRegion(100, 100, 400, 300); // fit a world-coordinate region
158
159
  ```
159
160
 
@@ -255,7 +256,7 @@ const inside = api.isPointInDrawing(world.x, world.y);
255
256
  | Option | Type | Default | Description |
256
257
  |--------|------|---------|-------------|
257
258
  | `fitOnLoad` | `boolean` | `true` | Auto-fit drawing to viewport on load |
258
- | `fitPadding` | `number` | `50` | Default padding for fit operations (px) |
259
+ | `fitPadding` | `number` | `0` | Default padding for fit operations (px) |
259
260
 
260
261
  ### Pan Clamping
261
262
 
@@ -368,11 +369,10 @@ These still work but the `on()`/`off()` event emitter is preferred.
368
369
 
369
370
  | Method | Description |
370
371
  |--------|-------------|
371
- | `fit(padding?)` | Fit main drawing to viewport |
372
+ | `fit(opts?)` | Fit main drawing to viewport. Options: `{ animate, padding, duration, easing }` |
372
373
  | `fitToDrawing(id, padding?)` | Fit a specific additional drawing to viewport |
373
374
  | `fitAll(padding?)` | Fit all drawings (main + additional) to viewport |
374
375
  | `panTo(x, y, zoom?)` | Center viewport on world coordinate, optionally set zoom |
375
- | `panToElement(eleOrId, padding?)` | Fit a cytoscape element in viewport (accepts ID string or element) |
376
376
  | `panToRegion(x, y, w, h, padding?)` | Fit a world-coordinate region in viewport |
377
377
 
378
378
  ### Visibility
@@ -440,6 +440,14 @@ These still work but the `on()`/`off()` event emitter is preferred.
440
440
 
441
441
  ## Changelog
442
442
 
443
+ ### 1.3.0
444
+
445
+ - **Breaking**: `fit()` now accepts an options object instead of a padding number: `fit({ animate, padding, duration, easing })`. Calling `fit()` with no arguments still works (uses defaults).
446
+ - **Breaking**: Removed `panToElement()` — use application-level implementation for element navigation with custom zoom/animation logic.
447
+ - **Changed**: Default `fitPadding` changed from `50` to `0`.
448
+ - **Added**: `fit()` now supports `animate` option with configurable `duration` (default 300ms) and `easing` (default `ease-in-out-cubic`).
449
+ - **Added**: `fit()` now calls `cy.resize()` before calculating dimensions.
450
+
443
451
  ### 1.2.3
444
452
 
445
453
  - **Fix**: `_springBackIfNeeded` now respects `panClamp: false`. Previously, setting `panClamp: false` at runtime disabled hard clamping but the soft spring-back animation on mouse release still fired, snapping the viewport back to drawing bounds. This made it impossible to programmatically disable pan clamping (e.g., during `panToElement` animations).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cytoscape-canvas-underlay",
3
- "version": "1.2.4",
3
+ "version": "1.3.0",
4
4
  "description": "Cytoscape.js plugin for rendering image/PDF canvas underlay behind graph nodes with synchronized zoom and pan",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -24,7 +24,7 @@ const DEFAULTS = {
24
24
  // ── Layout ──
25
25
  zIndex: 0, // Canvas z-index within overlay container
26
26
  fitOnLoad: true, // Auto-fit drawing to viewport on load
27
- fitPadding: 50, // Padding (px) for fit operations
27
+ fitPadding: 0, // Padding (px) for fit operations
28
28
 
29
29
  // ── Pan Clamping ──
30
30
  panClamp: false, // Prevent panning too far from drawing bounds
@@ -721,22 +721,31 @@ export class DrawingOverlay {
721
721
  ═══════════════════════════════════════ */
722
722
 
723
723
  /** Fit the main drawing to viewport. */
724
- fit(padding) {
724
+ fit({
725
+ animate = false,
726
+ padding = this.opts.fitPadding,
727
+ duration = 300,
728
+ easing = 'ease-in-out-cubic',
729
+ } = {}) {
725
730
  if (!this._main.w || !this._main.h) return;
726
- const pad = padding ?? this.opts.fitPadding;
727
- const container = this.cy.container().getBoundingClientRect();
728
- const scaleX = (container.width - pad * 2) / this._main.w;
729
- const scaleY = (container.height - pad * 2) / this._main.h;
730
- const zoom = Math.max(this.cy.minZoom(), Math.min(this.cy.maxZoom(),Math.min(scaleX, scaleY)));
731
+ const cy = this.cy;
731
732
 
732
- this.cy.zoom({
733
- level: zoom,
734
- renderedPosition: { x: container.width / 2, y: container.height / 2 },
735
- });
736
- this.cy.pan({
737
- x: (container.width - this._main.w * zoom) / 2,
738
- y: (container.height - this._main.h * zoom) / 2,
739
- });
733
+ cy.resize();
734
+
735
+ const container = cy.container().getBoundingClientRect();
736
+ const cw = container.width - padding * 2;
737
+ const ch = container.height - padding * 2;
738
+ if (cw <= 0 || ch <= 0) return;
739
+
740
+ const scale = Math.min(cw / this._main.w, ch / this._main.h);
741
+ const panX = Math.round(padding + (cw - this._main.w * scale) / 2);
742
+ const panY = Math.round(padding + (ch - this._main.h * scale) / 2);
743
+
744
+ if (animate) {
745
+ cy.animate({ zoom: scale, pan: { x: panX, y: panY }, duration, easing });
746
+ } else {
747
+ cy.viewport({ zoom: scale, pan: { x: panX, y: panY } });
748
+ }
740
749
  }
741
750
 
742
751
  /** Fit a specific additional drawing to viewport. */
@@ -802,34 +811,6 @@ export class DrawingOverlay {
802
811
  });
803
812
  }
804
813
 
805
- /** Pan to center a cytoscape element in viewport. */
806
- panToElement(eleOrId, padding) {
807
- const cy = this.cy;
808
- const ele = typeof eleOrId === 'string' ? cy.getElementById(eleOrId) : eleOrId;
809
- if (!ele || ele.empty?.()) return;
810
-
811
- const bb = ele.boundingBox();
812
- const pad = padding ?? this.opts.fitPadding;
813
- const container = cy.container().getBoundingClientRect();
814
-
815
- // Calculate zoom to fit element
816
- const scaleX = (container.width - pad * 2) / bb.w;
817
- const scaleY = (container.height - pad * 2) / bb.h;
818
- const zoom = Math.max(this.cy.minZoom(), Math.min(this.cy.maxZoom(),Math.min(scaleX, scaleY)));
819
-
820
- const cx = (bb.x1 + bb.x2) / 2;
821
- const cy_ = (bb.y1 + bb.y2) / 2;
822
-
823
- this.cy.zoom({
824
- level: zoom,
825
- renderedPosition: { x: container.width / 2, y: container.height / 2 },
826
- });
827
- this.cy.pan({
828
- x: container.width / 2 - cx * zoom,
829
- y: container.height / 2 - cy_ * zoom,
830
- });
831
- }
832
-
833
814
  /** Pan to a specific region of the drawing. */
834
815
  panToRegion(x, y, w, h, padding) {
835
816
  const pad = padding ?? this.opts.fitPadding;
package/src/index.js CHANGED
@@ -38,11 +38,10 @@ function register(cytoscape) {
38
38
  getRotation() { return overlay.getRotation(); },
39
39
 
40
40
  // ── Navigation ──
41
- fit(padding) { overlay.fit(padding); },
41
+ fit(opts) { overlay.fit(opts); },
42
42
  fitToDrawing(id, padding) { overlay.fitToDrawing(id, padding); },
43
43
  fitAll(padding) { overlay.fitAll(padding); },
44
44
  panTo(x, y, zoom) { overlay.panTo(x, y, zoom); },
45
- panToElement(eleOrId, padding) { overlay.panToElement(eleOrId, padding); },
46
45
  panToRegion(x, y, w, h, padding) { overlay.panToRegion(x, y, w, h, padding); },
47
46
 
48
47
  // ── Visibility ──