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 +15 -7
- package/package.json +1 -1
- package/src/DrawingOverlay.js +24 -43
- package/src/index.js +1 -2
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`, `
|
|
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` | `
|
|
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(
|
|
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.
|
|
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",
|
package/src/DrawingOverlay.js
CHANGED
|
@@ -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:
|
|
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(
|
|
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
|
|
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
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
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(
|
|
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 ──
|