@neo4j-nvl/interaction-handlers 0.2.1
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/Neo4j Early Access Agreement - Visualization Library.pdf +0 -0
- package/README.md +1 -0
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +1 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.js +8 -0
- package/lib/interaction-handlers/base.d.ts +54 -0
- package/lib/interaction-handlers/base.js +110 -0
- package/lib/interaction-handlers/click-interaction.d.ts +109 -0
- package/lib/interaction-handlers/click-interaction.js +162 -0
- package/lib/interaction-handlers/drag-node-interaction.d.ts +46 -0
- package/lib/interaction-handlers/drag-node-interaction.js +137 -0
- package/lib/interaction-handlers/draw-interaction.d.ts +30 -0
- package/lib/interaction-handlers/draw-interaction.js +257 -0
- package/lib/interaction-handlers/hover-interaction.d.ts +57 -0
- package/lib/interaction-handlers/hover-interaction.js +113 -0
- package/lib/interaction-handlers/multi-select-interaction.d.ts +58 -0
- package/lib/interaction-handlers/multi-select-interaction.js +133 -0
- package/lib/interaction-handlers/pan-interaction.d.ts +58 -0
- package/lib/interaction-handlers/pan-interaction.js +115 -0
- package/lib/interaction-handlers/utils.d.ts +1 -0
- package/lib/interaction-handlers/utils.js +1 -0
- package/lib/interaction-handlers/zoom-interaction.d.ts +52 -0
- package/lib/interaction-handlers/zoom-interaction.js +91 -0
- package/lib/overlay-renderer/overlay-renderer.d.ts +12 -0
- package/lib/overlay-renderer/overlay-renderer.js +111 -0
- package/package.json +36 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { NVL } from '@neo4j-nvl/core';
|
|
2
|
+
import { BaseInteraction } from './base';
|
|
3
|
+
/**
|
|
4
|
+
* Callbacks for the pan interaction handler.
|
|
5
|
+
*/
|
|
6
|
+
export type PanInteractionCallbacks = {
|
|
7
|
+
/**
|
|
8
|
+
* Called when the canvas is panned.
|
|
9
|
+
* @param panning - The panning coordinates
|
|
10
|
+
*/
|
|
11
|
+
onPan: (panning: {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
}) => void;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Interaction handler for panning the canvas.
|
|
18
|
+
* Panning is achieved by clicking and dragging on the canvas.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```js
|
|
22
|
+
* const nvl = new NVL(container, nodes, relationships)
|
|
23
|
+
* const panInteraction = new PanInteraction(nvl)
|
|
24
|
+
*
|
|
25
|
+
* panInteraction.updateCallback('onPan', (panning) => {
|
|
26
|
+
* console.log('Panning:', panning)
|
|
27
|
+
* })
|
|
28
|
+
*/
|
|
29
|
+
export declare class PanInteraction extends BaseInteraction<PanInteractionCallbacks> {
|
|
30
|
+
private mousePosition;
|
|
31
|
+
private targets;
|
|
32
|
+
private excludeNodeMargin;
|
|
33
|
+
private shouldPan;
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new instance of the pan interaction handler.
|
|
36
|
+
* @param nvl - The NVL instance to attach the interaction handler to
|
|
37
|
+
*/
|
|
38
|
+
constructor(nvl: NVL);
|
|
39
|
+
/**
|
|
40
|
+
* Updates which type of graph elements should hinder panning.
|
|
41
|
+
* @param targets - The graph elements that should hinder panning
|
|
42
|
+
* @param excludeNodeMargin - If true, the node margin will not hinder panning
|
|
43
|
+
* @note By default, panning is hindered by nodes and relationships.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```js
|
|
47
|
+
* // Pan canvas even when dragging on nodes and relationships
|
|
48
|
+
* panInteraction.updateTargets([], true)
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
updateTargets: (targets: Array<'node' | 'relationship'>, excludeNodeMargin: boolean) => void;
|
|
52
|
+
private handleMouseDown;
|
|
53
|
+
private handleMouseMove;
|
|
54
|
+
/**
|
|
55
|
+
* Removes the related event listeners from the canvas.
|
|
56
|
+
*/
|
|
57
|
+
destroy(): void;
|
|
58
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { difference } from 'lodash';
|
|
2
|
+
import { NODE_EDGE_WIDTH } from '../constants';
|
|
3
|
+
import { BaseInteraction } from './base';
|
|
4
|
+
/**
|
|
5
|
+
* Interaction handler for panning the canvas.
|
|
6
|
+
* Panning is achieved by clicking and dragging on the canvas.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```js
|
|
10
|
+
* const nvl = new NVL(container, nodes, relationships)
|
|
11
|
+
* const panInteraction = new PanInteraction(nvl)
|
|
12
|
+
*
|
|
13
|
+
* panInteraction.updateCallback('onPan', (panning) => {
|
|
14
|
+
* console.log('Panning:', panning)
|
|
15
|
+
* })
|
|
16
|
+
*/
|
|
17
|
+
export class PanInteraction extends BaseInteraction {
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new instance of the pan interaction handler.
|
|
20
|
+
* @param nvl - The NVL instance to attach the interaction handler to
|
|
21
|
+
*/
|
|
22
|
+
constructor(nvl) {
|
|
23
|
+
super(nvl);
|
|
24
|
+
Object.defineProperty(this, "mousePosition", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: void 0
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "targets", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: void 0
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(this, "excludeNodeMargin", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: void 0
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(this, "shouldPan", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
writable: true,
|
|
46
|
+
value: void 0
|
|
47
|
+
});
|
|
48
|
+
/**
|
|
49
|
+
* Updates which type of graph elements should hinder panning.
|
|
50
|
+
* @param targets - The graph elements that should hinder panning
|
|
51
|
+
* @param excludeNodeMargin - If true, the node margin will not hinder panning
|
|
52
|
+
* @note By default, panning is hindered by nodes and relationships.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```js
|
|
56
|
+
* // Pan canvas even when dragging on nodes and relationships
|
|
57
|
+
* panInteraction.updateTargets([], true)
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
Object.defineProperty(this, "updateTargets", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
configurable: true,
|
|
63
|
+
writable: true,
|
|
64
|
+
value: (targets, excludeNodeMargin) => {
|
|
65
|
+
this.targets = targets;
|
|
66
|
+
this.excludeNodeMargin = excludeNodeMargin;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
Object.defineProperty(this, "handleMouseDown", {
|
|
70
|
+
enumerable: true,
|
|
71
|
+
configurable: true,
|
|
72
|
+
writable: true,
|
|
73
|
+
value: (event) => {
|
|
74
|
+
const hits = this.nvlInstance.getHits(event, difference(['node', 'relationship'], this.targets), { hitNodeMarginWidth: this.excludeNodeMargin ? NODE_EDGE_WIDTH : 0 });
|
|
75
|
+
if (hits.nvlTargets.nodes.length > 0 || hits.nvlTargets.relationships.length > 0) {
|
|
76
|
+
this.shouldPan = false;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.mousePosition = { x: event.clientX, y: event.clientY };
|
|
80
|
+
this.shouldPan = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(this, "handleMouseMove", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
configurable: true,
|
|
87
|
+
writable: true,
|
|
88
|
+
value: (evt) => {
|
|
89
|
+
if (!this.shouldPan || evt.buttons !== 1) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const zoom = this.nvlInstance.getScale();
|
|
93
|
+
const { x, y } = this.nvlInstance.getPan();
|
|
94
|
+
const dx = (evt.clientX - this.mousePosition.x) / zoom * window.devicePixelRatio;
|
|
95
|
+
const dy = (evt.clientY - this.mousePosition.y) / zoom * window.devicePixelRatio;
|
|
96
|
+
this.nvlInstance.setPan(x - dx, y - dy);
|
|
97
|
+
this.callCallbackIfRegistered('onPan', { x: x - dx, y: y - dy });
|
|
98
|
+
this.mousePosition = { x: evt.clientX, y: evt.clientY };
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
this.mousePosition = { x: 0, y: 0 };
|
|
102
|
+
this.targets = [];
|
|
103
|
+
this.excludeNodeMargin = false;
|
|
104
|
+
this.shouldPan = false;
|
|
105
|
+
this.addEventListener('mousedown', this.handleMouseDown, true);
|
|
106
|
+
this.addEventListener('mousemove', this.handleMouseMove, true);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Removes the related event listeners from the canvas.
|
|
110
|
+
*/
|
|
111
|
+
destroy() {
|
|
112
|
+
this.removeEventListener('mousedown', this.handleMouseDown, true);
|
|
113
|
+
this.removeEventListener('mousemove', this.handleMouseMove, true);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const generateUniqueId: (digit: number) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const generateUniqueId = (digit) => Math.floor((Math.random() * Math.pow(10, digit))).toString();
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { NVL } from '@neo4j-nvl/core';
|
|
2
|
+
import { BaseInteraction } from './base';
|
|
3
|
+
/**
|
|
4
|
+
* Callbacks for the zoom interaction handler.
|
|
5
|
+
*/
|
|
6
|
+
export type ZoomInteractionCallbacks = {
|
|
7
|
+
/**
|
|
8
|
+
* Called when the canvas is zoomed.
|
|
9
|
+
* @param zoomLevel - The zoom level
|
|
10
|
+
*/
|
|
11
|
+
onZoom: (zoomLevel: number) => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Interaction handler for zooming the canvas.
|
|
15
|
+
* Zooming is achieved by scrolling the mouse wheel on the canvas.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```js
|
|
19
|
+
* const nvl = new NVL(container, nodes, relationships)
|
|
20
|
+
* const zoomInteraction = new ZoomInteraction(nvl)
|
|
21
|
+
*
|
|
22
|
+
* zoomInteraction.updateCallback('onZoom', (zoomLevel) => {
|
|
23
|
+
* console.log('Zoom level:', zoomLevel)
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class ZoomInteraction extends BaseInteraction<ZoomInteractionCallbacks> {
|
|
28
|
+
private MinZoom;
|
|
29
|
+
private MaxZoom;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new instance of the zoom interaction handler.
|
|
32
|
+
* @param nvl - The NVL instance to attach the interaction handler to
|
|
33
|
+
*/
|
|
34
|
+
constructor(nvl: NVL);
|
|
35
|
+
/**
|
|
36
|
+
* Throttled zoom function to avoid events happening too fast.
|
|
37
|
+
* @param event - The original mouse wheel event
|
|
38
|
+
* @note "Wheel" with a touchpad, the wheel is triggered event a lot,
|
|
39
|
+
* especially a lot of very small values.
|
|
40
|
+
* However, updating values in NVL instance takes time.
|
|
41
|
+
* Sometimes it lost the track of multiple events happening too soon.
|
|
42
|
+
* As a result, the zoom might lose its anchor point under touch pad.
|
|
43
|
+
* Therefore, the throttle is needed to avoid events happening too fast.
|
|
44
|
+
* @note The throttle is set to 25ms.
|
|
45
|
+
*/
|
|
46
|
+
private throttledZoom;
|
|
47
|
+
private handleWheel;
|
|
48
|
+
/**
|
|
49
|
+
* Removes the relevant event listeners from the canvas.
|
|
50
|
+
*/
|
|
51
|
+
destroy: () => void;
|
|
52
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { throttle } from 'lodash';
|
|
2
|
+
import { BaseInteraction } from './base';
|
|
3
|
+
/**
|
|
4
|
+
* Interaction handler for zooming the canvas.
|
|
5
|
+
* Zooming is achieved by scrolling the mouse wheel on the canvas.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```js
|
|
9
|
+
* const nvl = new NVL(container, nodes, relationships)
|
|
10
|
+
* const zoomInteraction = new ZoomInteraction(nvl)
|
|
11
|
+
*
|
|
12
|
+
* zoomInteraction.updateCallback('onZoom', (zoomLevel) => {
|
|
13
|
+
* console.log('Zoom level:', zoomLevel)
|
|
14
|
+
* })
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export class ZoomInteraction extends BaseInteraction {
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new instance of the zoom interaction handler.
|
|
20
|
+
* @param nvl - The NVL instance to attach the interaction handler to
|
|
21
|
+
*/
|
|
22
|
+
constructor(nvl) {
|
|
23
|
+
super(nvl);
|
|
24
|
+
Object.defineProperty(this, "MinZoom", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: void 0
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "MaxZoom", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: void 0
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Throttled zoom function to avoid events happening too fast.
|
|
38
|
+
* @param event - The original mouse wheel event
|
|
39
|
+
* @note "Wheel" with a touchpad, the wheel is triggered event a lot,
|
|
40
|
+
* especially a lot of very small values.
|
|
41
|
+
* However, updating values in NVL instance takes time.
|
|
42
|
+
* Sometimes it lost the track of multiple events happening too soon.
|
|
43
|
+
* As a result, the zoom might lose its anchor point under touch pad.
|
|
44
|
+
* Therefore, the throttle is needed to avoid events happening too fast.
|
|
45
|
+
* @note The throttle is set to 25ms.
|
|
46
|
+
*/
|
|
47
|
+
Object.defineProperty(this, "throttledZoom", {
|
|
48
|
+
enumerable: true,
|
|
49
|
+
configurable: true,
|
|
50
|
+
writable: true,
|
|
51
|
+
value: throttle((event) => {
|
|
52
|
+
const zoom = this.nvlInstance.getScale();
|
|
53
|
+
const { x, y } = this.nvlInstance.getPan();
|
|
54
|
+
const factor = event.deltaY / 500;
|
|
55
|
+
const newZoomTarget = zoom - factor * Math.min(1, zoom);
|
|
56
|
+
if (newZoomTarget < this.MinZoom || newZoomTarget > this.MaxZoom) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.nvlInstance.setZoom(newZoomTarget);
|
|
60
|
+
this.callCallbackIfRegistered('onZoom', newZoomTarget);
|
|
61
|
+
const { offsetX, offsetY } = this.nvlInstance.getMouseElementCoordinates(event);
|
|
62
|
+
const newPanX = x + (offsetX / zoom - offsetX / newZoomTarget);
|
|
63
|
+
const newPanY = y + (offsetY / zoom - offsetY / newZoomTarget);
|
|
64
|
+
this.nvlInstance.setPan(newPanX, newPanY);
|
|
65
|
+
}, 25, { leading: true })
|
|
66
|
+
});
|
|
67
|
+
Object.defineProperty(this, "handleWheel", {
|
|
68
|
+
enumerable: true,
|
|
69
|
+
configurable: true,
|
|
70
|
+
writable: true,
|
|
71
|
+
value: (evt) => {
|
|
72
|
+
evt.preventDefault();
|
|
73
|
+
this.throttledZoom(evt);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* Removes the relevant event listeners from the canvas.
|
|
78
|
+
*/
|
|
79
|
+
Object.defineProperty(this, "destroy", {
|
|
80
|
+
enumerable: true,
|
|
81
|
+
configurable: true,
|
|
82
|
+
writable: true,
|
|
83
|
+
value: () => {
|
|
84
|
+
this.removeEventListener('wheel', this.handleWheel);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
this.MinZoom = 0.1;
|
|
88
|
+
this.MaxZoom = 5;
|
|
89
|
+
this.addEventListener('wheel', this.handleWheel);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class OverlayRenderer {
|
|
2
|
+
private _ctx;
|
|
3
|
+
canvas: HTMLCanvasElement;
|
|
4
|
+
removeResizeListener: any;
|
|
5
|
+
constructor(canvasParent: HTMLElement);
|
|
6
|
+
_fixCanvasSize(canvas: HTMLCanvasElement): void;
|
|
7
|
+
_zoomAndPan(zoom: number, panX: number, panY: number): void;
|
|
8
|
+
drawBox(startX: number, startY: number, endX: number, endY: number): void;
|
|
9
|
+
drawNodeRing(x: number, y: number, radius: number, zoom: number, panX: number, panY: number): void;
|
|
10
|
+
clear(): void;
|
|
11
|
+
destroy(): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { drawCircleBand } from '@neo4j-nvl/core';
|
|
2
|
+
import onResize from 'resizelistener';
|
|
3
|
+
const marquee = {
|
|
4
|
+
frameWidth: 2,
|
|
5
|
+
frameColor: '#a9a9a9',
|
|
6
|
+
color: '#e0e0e0',
|
|
7
|
+
opacity: 0.5
|
|
8
|
+
};
|
|
9
|
+
export class OverlayRenderer {
|
|
10
|
+
constructor(canvasParent) {
|
|
11
|
+
Object.defineProperty(this, "_ctx", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true,
|
|
15
|
+
value: void 0
|
|
16
|
+
});
|
|
17
|
+
Object.defineProperty(this, "canvas", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
configurable: true,
|
|
20
|
+
writable: true,
|
|
21
|
+
value: void 0
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(this, "removeResizeListener", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true,
|
|
27
|
+
value: void 0
|
|
28
|
+
});
|
|
29
|
+
const canvas = document.createElement('canvas');
|
|
30
|
+
canvas.id = 'OVERLAY';
|
|
31
|
+
canvas.style.position = 'absolute';
|
|
32
|
+
canvas.style.top = '0';
|
|
33
|
+
canvas.style.bottom = '0';
|
|
34
|
+
canvas.style.left = '0';
|
|
35
|
+
canvas.style.right = '0';
|
|
36
|
+
// These are needed for touchpad zoom on Edge
|
|
37
|
+
canvas.style.touchAction = 'none';
|
|
38
|
+
// @ts-expect-error revisit later
|
|
39
|
+
canvas.style.msTouchAction = 'none';
|
|
40
|
+
canvasParent.appendChild(canvas);
|
|
41
|
+
const context = canvas.getContext('2d');
|
|
42
|
+
this._ctx = context;
|
|
43
|
+
this.canvas = canvas;
|
|
44
|
+
this.removeResizeListener = onResize(canvasParent, () => {
|
|
45
|
+
this._fixCanvasSize(canvas);
|
|
46
|
+
});
|
|
47
|
+
this._fixCanvasSize(canvas);
|
|
48
|
+
}
|
|
49
|
+
_fixCanvasSize(canvas) {
|
|
50
|
+
const parent = canvas.parentElement;
|
|
51
|
+
const rect = parent.getBoundingClientRect();
|
|
52
|
+
const width = rect.width;
|
|
53
|
+
const height = rect.height;
|
|
54
|
+
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
55
|
+
canvas.width = width * devicePixelRatio;
|
|
56
|
+
canvas.height = height * devicePixelRatio;
|
|
57
|
+
canvas.style.width = `${width}px`;
|
|
58
|
+
canvas.style.height = `${height}px`;
|
|
59
|
+
}
|
|
60
|
+
// Can be extracted as a util
|
|
61
|
+
_zoomAndPan(zoom, panX, panY) {
|
|
62
|
+
const { width, height } = this.canvas;
|
|
63
|
+
this._ctx.translate((-width / 2) * zoom, (-height / 2) * zoom);
|
|
64
|
+
this._ctx.translate(-panX * zoom, -panY * zoom);
|
|
65
|
+
this._ctx.scale(zoom, zoom);
|
|
66
|
+
this._ctx.translate(width / 2 / zoom, height / 2 / zoom);
|
|
67
|
+
this._ctx.translate(width / 2, height / 2);
|
|
68
|
+
}
|
|
69
|
+
drawBox(startX, startY, endX, endY) {
|
|
70
|
+
this.clear();
|
|
71
|
+
this._ctx.save();
|
|
72
|
+
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
73
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
74
|
+
const localStartX = (startX - rect.left) * devicePixelRatio;
|
|
75
|
+
const localStartY = (startY - rect.top) * devicePixelRatio;
|
|
76
|
+
const localEndX = (endX - rect.left) * devicePixelRatio;
|
|
77
|
+
const localEndY = (endY - rect.top) * devicePixelRatio;
|
|
78
|
+
if (!this._ctx)
|
|
79
|
+
return;
|
|
80
|
+
this._ctx.beginPath();
|
|
81
|
+
this._ctx.rect(localStartX, localStartY, localEndX - localStartX, localEndY - localStartY);
|
|
82
|
+
this._ctx.closePath();
|
|
83
|
+
this._ctx.strokeStyle = marquee.frameColor;
|
|
84
|
+
this._ctx.lineWidth = marquee.frameWidth * devicePixelRatio;
|
|
85
|
+
this._ctx.fillStyle = marquee.color;
|
|
86
|
+
this._ctx.globalAlpha = marquee.opacity;
|
|
87
|
+
this._ctx.stroke();
|
|
88
|
+
this._ctx.fill();
|
|
89
|
+
}
|
|
90
|
+
drawNodeRing(x, y, radius, zoom, panX, panY) {
|
|
91
|
+
this.clear();
|
|
92
|
+
this._ctx.save();
|
|
93
|
+
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
94
|
+
this._zoomAndPan(zoom, panX, panY);
|
|
95
|
+
// TODO: make 0.2 configurable from state and same as colour
|
|
96
|
+
const width = (radius !== null && radius !== void 0 ? radius : 25) * devicePixelRatio * 0.2;
|
|
97
|
+
drawCircleBand(this._ctx, x, y, (radius !== null && radius !== void 0 ? radius : 25) * devicePixelRatio, [{ width, color: 'blue' }]);
|
|
98
|
+
this._ctx.restore();
|
|
99
|
+
}
|
|
100
|
+
clear() {
|
|
101
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
102
|
+
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
103
|
+
if (!this._ctx)
|
|
104
|
+
return;
|
|
105
|
+
this._ctx.clearRect(0, 0, rect.width * devicePixelRatio, rect.height * devicePixelRatio);
|
|
106
|
+
}
|
|
107
|
+
destroy() {
|
|
108
|
+
this.removeResizeListener();
|
|
109
|
+
this.canvas.remove();
|
|
110
|
+
}
|
|
111
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@neo4j-nvl/interaction-handlers",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"license": "SEE LICENSE IN 'Neo4j Early Access Agreement - Visualization Library.pdf'",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"Neo4j Early Access Agreement - Visualization Library.pdf",
|
|
9
|
+
"lib"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"prebuild": "rm -rf lib/",
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"prepack": "cp ../../Neo4j\\ Early\\ Access\\ Agreement\\ -\\ Visualization\\ Library.pdf ./",
|
|
16
|
+
"postpack": "rm Neo4j\\ Early\\ Access\\ Agreement\\ -\\ Visualization\\ Library.pdf"
|
|
17
|
+
},
|
|
18
|
+
"typedoc": {
|
|
19
|
+
"entryPoint": "./src/index.ts",
|
|
20
|
+
"readmeFile": "./README.md",
|
|
21
|
+
"displayName": "Interaction Handlers",
|
|
22
|
+
"tsconfig": "./tsconfig.json"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"yarn": "^1.10.1"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"lodash": "^4.17.21",
|
|
29
|
+
"resizelistener": "^1.1.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@testing-library/jest-dom": "^5.16.5",
|
|
33
|
+
"@testing-library/react": "^13.4.0",
|
|
34
|
+
"@types/lodash": "^4.14.184"
|
|
35
|
+
}
|
|
36
|
+
}
|