@cosmograph/cosmos
Advanced tools
Comparing version 2.0.0-alpha.8 to 2.0.0-alpha.9
import { D3ZoomEvent } from 'd3-zoom'; | ||
import { D3DragEvent } from 'd3-drag'; | ||
import { type Hovered } from "./modules/Store"; | ||
export interface GraphEvents { | ||
@@ -24,6 +26,7 @@ /** | ||
* and the corresponding mouse event or D3's zoom event as the third argument: | ||
* `(index: number, pointPosition: [number, number], event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined) => void`. | ||
* `(index: number, pointPosition: [number, number], event: MouseEvent | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | ||
* | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onPointMouseOver?: (index: number, pointPosition: [number, number], event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined) => void; | ||
onPointMouseOver?: (index: number, pointPosition: [number, number], event: MouseEvent | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined) => void; | ||
/** | ||
@@ -33,6 +36,6 @@ * Callback function that will be called when a point is no longer underneath | ||
* The corresponding mouse event or D3's zoom event will be passed as the first argument: | ||
* `(event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined) => void`. | ||
* `(event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined> | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | undefined) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onPointMouseOut?: (event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined) => void; | ||
onPointMouseOut?: (event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined> | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | undefined) => void; | ||
/** | ||
@@ -62,2 +65,23 @@ * Callback function that will be called when zooming or panning starts. | ||
onZoomEnd?: (e: D3ZoomEvent<HTMLCanvasElement, undefined>, userDriven: boolean) => void; | ||
/** | ||
* Callback function that will be called when dragging starts. | ||
* First argument is a D3 Drag Event: | ||
* `(event: D3DragEvent) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onDragStart?: (e: D3DragEvent<HTMLCanvasElement, undefined, Hovered>) => void; | ||
/** | ||
* Callback function that will be called continuously during dragging. | ||
* First argument is a D3 Drag Event: | ||
* `(event: D3DragEvent) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onDrag?: (e: D3DragEvent<HTMLCanvasElement, undefined, Hovered>) => void; | ||
/** | ||
* Callback function that will be called when dragging ends. | ||
* First argument is a D3 Drag Event: | ||
* `(event: D3DragEvent) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onDragEnd?: (e: D3DragEvent<HTMLCanvasElement, undefined, Hovered>) => void; | ||
} | ||
@@ -323,2 +347,7 @@ export interface GraphSimulationSettings { | ||
/** | ||
* Disables dragging points. | ||
* Default: `false` | ||
*/ | ||
disableDrag?: boolean; | ||
/** | ||
* Whether to center and zoom the view to fit all points in the scene on initialization or not. | ||
@@ -388,2 +417,3 @@ * Default: `true` | ||
disableZoom: boolean; | ||
disableDrag: boolean; | ||
fitViewOnInit: boolean; | ||
@@ -390,0 +420,0 @@ fitViewDelay: number; |
@@ -22,2 +22,3 @@ import 'd3-transition'; | ||
private zoomInstance; | ||
private dragInstance; | ||
private fpsMonitor; | ||
@@ -41,2 +42,5 @@ private hasParticleSystemDestroyed; | ||
constructor(canvas: HTMLCanvasElement, config?: GraphConfigInterface); | ||
/** | ||
* Returns the current simulation progress | ||
*/ | ||
get progress(): number; | ||
@@ -57,9 +61,71 @@ /** | ||
setConfig(config: Partial<GraphConfigInterface>): void; | ||
/** | ||
* Sets the positions for the graph points. | ||
* | ||
* @param {number[]} pointPositions - An array representing the positions of points in the format [x1, y1, x2, y2, ..., xn, yn], | ||
* where `n` is the index of the point. | ||
* Example: `[1, 2, 3, 4, 5, 6]` sets the first point to (1, 2), the second point to (3, 4), and so on. | ||
*/ | ||
setPointPositions(pointPositions: number[]): void; | ||
/** | ||
* Sets the colors for the graph points. | ||
* | ||
* @param {number[]} pointColors - An array representing the colors of points in the format [r1, g1, b1, a1, r2, g2, b2, a2, ..., rn, gn, bn, an], | ||
* where each color is represented in RGBA format. | ||
* Example: `[255, 0, 0, 1, 0, 255, 0, 1]` sets the first point to red and the second point to green. | ||
*/ | ||
setPointColors(pointColors: number[]): void; | ||
/** | ||
* Sets the sizes for the graph points. | ||
* | ||
* @param {number[]} pointSizes - An array representing the sizes of points in the format [size1, size2, ..., sizen], | ||
* where `n` is the index of the point. | ||
* Example: `[10, 20, 30]` sets the first point to size 10, the second point to size 20, and the third point to size 30. | ||
*/ | ||
setPointSizes(pointSizes: number[]): void; | ||
/** | ||
* Sets the links for the graph. | ||
* | ||
* @param {number[]} links - An array representing the links between points in the format [source1, target1, source2, target2, ..., sourcen, targetn], | ||
* where `source` and `target` are the indices of the points being linked. | ||
* Example: `[0, 1, 1, 2]` creates a link from point 0 to point 1 and another link from point 1 to point 2. | ||
*/ | ||
setLinks(links: number[]): void; | ||
/** | ||
* Sets the colors for the graph links. | ||
* | ||
* @param {number[]} linkColors - An array representing the colors of links in the format [r1, g1, b1, a1, r2, g2, b2, a2, ..., rn, gn, bn, an], | ||
* where each color is in RGBA format. | ||
* Example: `[255, 0, 0, 1, 0, 255, 0, 1]` sets the first link to red and the second link to green. | ||
*/ | ||
setLinkColors(linkColors: number[]): void; | ||
/** | ||
* Sets the widths for the graph links. | ||
* | ||
* @param {number[]} linkWidths - An array representing the widths of links in the format [width1, width2, ..., widthn], | ||
* where `n` is the index of the link. | ||
* Example: `[1, 2, 3]` sets the first link to width 1, the second link to width 2, and the third link to width 3. | ||
*/ | ||
setLinkWidths(linkWidths: number[]): void; | ||
/** | ||
* Sets the arrows for the graph links. | ||
* | ||
* @param {boolean[]} linkArrows - An array of booleans indicating whether each link should have an arrow, | ||
* in the format [arrow1, arrow2, ..., arrown], where `n` is the index of the link. | ||
* Example: `[true, false, true]` sets arrows on the first and third links, but not on the second link. | ||
*/ | ||
setLinkArrows(linkArrows: boolean[]): void; | ||
/** | ||
* Sets the strength for the graph links. | ||
* | ||
* @param {number[]} linkStrength - An array representing the strength of each link in the format [strength1, strength2, ..., strengthn], | ||
* where `n` is the index of the link. | ||
* Example: `[1, 2, 3]` sets the first link to strength 1, the second link to strength 2, and the third link to strength 3. | ||
*/ | ||
setLinkStrength(linkStrength: number[]): void; | ||
/** | ||
* Renders the graph. | ||
* | ||
* @param {boolean} [runSimulation=true] - Optional flag to determine if the simulation should run on render. | ||
*/ | ||
render(runSimulation?: boolean): void; | ||
@@ -241,6 +307,6 @@ /** | ||
private setZoomTransformByPointPositions; | ||
private disableZoom; | ||
private enableZoom; | ||
private updateZoomDragBehaviors; | ||
private findHoveredPoint; | ||
private updateCanvasCursor; | ||
} | ||
export type { GraphConfigInterface, GraphEvents, GraphSimulationSettings } from './config'; |
@@ -7,2 +7,3 @@ import { GraphConfig } from "../../config"; | ||
inputLinkWidths: number[] | undefined; | ||
inputLinkStrength: number[] | undefined; | ||
pointPositions: number[] | undefined; | ||
@@ -16,4 +17,10 @@ pointColors: number[] | undefined; | ||
linkArrows: number[] | undefined; | ||
sourceIndexToTargetIndices: (number[] | undefined)[] | undefined; | ||
targetIndexToSourceIndices: (number[] | undefined)[] | undefined; | ||
linkStrength: (number | undefined)[] | undefined; | ||
/** | ||
* Each inner array of `sourceIndexToTargetIndices` and `targetIndexToSourceIndices` contains pairs where: | ||
* - The first value is the target/source index in the node array. | ||
* - The second value is the link index in the array of links. | ||
*/ | ||
sourceIndexToTargetIndices: ([number, number][] | undefined)[] | undefined; | ||
targetIndexToSourceIndices: ([number, number][] | undefined)[] | undefined; | ||
degree: number[] | undefined; | ||
@@ -44,2 +51,3 @@ private _config; | ||
updateArrows(): void; | ||
updateLinkStrength(): void; | ||
update(): void; | ||
@@ -46,0 +54,0 @@ getAdjacentIndices(index: number): number[] | undefined; |
@@ -19,2 +19,3 @@ import regl from 'regl'; | ||
private updatePositionCommand; | ||
private dragPointCommand; | ||
private findPointsOnAreaSelectionCommand; | ||
@@ -36,2 +37,3 @@ private findHoveredPointCommand; | ||
updatePosition(): void; | ||
drag(): void; | ||
findPointsOnAreaSelection(): void; | ||
@@ -38,0 +40,0 @@ findHoveredPoint(): void; |
import { mat3 } from 'gl-matrix'; | ||
export declare const ALPHA_MIN = 0.001; | ||
export declare const MAX_POINT_SIZE = 64; | ||
declare type Hovered = { | ||
export declare type Hovered = { | ||
index: number; | ||
@@ -27,2 +27,3 @@ position: [number, number]; | ||
focusedPoint: Focused | undefined; | ||
draggingPointIndex: number | undefined; | ||
adjustedSpaceSize: number; | ||
@@ -29,0 +30,0 @@ hoveredPointRingColor: number[]; |
@@ -42,2 +42,3 @@ export declare const defaultPointColor = "#b3b3b3"; | ||
disableZoom: boolean; | ||
disableDrag: boolean; | ||
fitViewOnInit: boolean; | ||
@@ -44,0 +45,0 @@ fitViewDelay: number; |
{ | ||
"name": "@cosmograph/cosmos", | ||
"version": "2.0.0-alpha.8", | ||
"version": "2.0.0-alpha.9", | ||
"description": "GPU-based force graph layout and rendering", | ||
@@ -37,2 +37,3 @@ "jsdelivr": "dist/index.min.js", | ||
"@types/d3-color": "^3.1.0", | ||
"@types/d3-drag": "^3.0.7", | ||
"@types/d3-ease": "^3.0.0", | ||
@@ -63,2 +64,3 @@ "@types/d3-scale": "^4.0.2", | ||
"d3-color": "^3.1.0", | ||
"d3-drag": "^3.0.0", | ||
"d3-ease": "^3.0.1", | ||
@@ -65,0 +67,0 @@ "d3-scale": "^4.0.2", |
import { D3ZoomEvent } from 'd3-zoom' | ||
import { D3DragEvent } from 'd3-drag' | ||
import { | ||
@@ -13,2 +14,3 @@ defaultPointColor, | ||
import { isPlainObject } from '@/graph/helper' | ||
import { type Hovered } from '@/graph/modules/Store' | ||
@@ -41,7 +43,10 @@ export interface GraphEvents { | ||
* and the corresponding mouse event or D3's zoom event as the third argument: | ||
* `(index: number, pointPosition: [number, number], event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined) => void`. | ||
* `(index: number, pointPosition: [number, number], event: MouseEvent | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | ||
* | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onPointMouseOver?: ( | ||
index: number, pointPosition: [number, number], event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined | ||
index: number, | ||
pointPosition: [number, number], | ||
event: MouseEvent | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined | ||
) => void; | ||
@@ -52,6 +57,6 @@ /** | ||
* The corresponding mouse event or D3's zoom event will be passed as the first argument: | ||
* `(event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined) => void`. | ||
* `(event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined> | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | undefined) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onPointMouseOut?: (event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined> | undefined) => void; | ||
onPointMouseOut?: (event: MouseEvent | D3ZoomEvent<HTMLCanvasElement, undefined> | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | undefined) => void; | ||
/** | ||
@@ -81,2 +86,23 @@ * Callback function that will be called when zooming or panning starts. | ||
onZoomEnd?: (e: D3ZoomEvent<HTMLCanvasElement, undefined>, userDriven: boolean) => void; | ||
/** | ||
* Callback function that will be called when dragging starts. | ||
* First argument is a D3 Drag Event: | ||
* `(event: D3DragEvent) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onDragStart?: (e: D3DragEvent<HTMLCanvasElement, undefined, Hovered>) => void; | ||
/** | ||
* Callback function that will be called continuously during dragging. | ||
* First argument is a D3 Drag Event: | ||
* `(event: D3DragEvent) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onDrag?: (e: D3DragEvent<HTMLCanvasElement, undefined, Hovered>) => void; | ||
/** | ||
* Callback function that will be called when dragging ends. | ||
* First argument is a D3 Drag Event: | ||
* `(event: D3DragEvent) => void`. | ||
* Default value: `undefined` | ||
*/ | ||
onDragEnd?: (e: D3DragEvent<HTMLCanvasElement, undefined, Hovered>) => void; | ||
} | ||
@@ -350,2 +376,7 @@ | ||
/** | ||
* Disables dragging points. | ||
* Default: `false` | ||
*/ | ||
disableDrag?: boolean; | ||
/** | ||
* Whether to center and zoom the view to fit all points in the scene on initialization or not. | ||
@@ -437,2 +468,5 @@ * Default: `true` | ||
onZoomEnd: undefined, | ||
onDragStart: undefined, | ||
onDrag: undefined, | ||
onDragEnd: undefined, | ||
} | ||
@@ -447,2 +481,3 @@ | ||
public disableZoom = defaultConfigValues.disableZoom | ||
public disableDrag = defaultConfigValues.disableDrag | ||
public fitViewOnInit = defaultConfigValues.fitViewOnInit | ||
@@ -449,0 +484,0 @@ public fitViewDelay = defaultConfigValues.fitViewDelay |
144
src/index.ts
@@ -5,2 +5,3 @@ import { select, Selection } from 'd3-selection' | ||
import { D3ZoomEvent } from 'd3-zoom' | ||
import { D3DragEvent } from 'd3-drag' | ||
import regl from 'regl' | ||
@@ -19,4 +20,5 @@ import { GraphConfig, GraphConfigInterface } from '@/graph/config' | ||
import { Points } from '@/graph/modules/Points' | ||
import { Store, ALPHA_MIN, MAX_POINT_SIZE } from '@/graph/modules/Store' | ||
import { Store, ALPHA_MIN, MAX_POINT_SIZE, type Hovered } from '@/graph/modules/Store' | ||
import { Zoom } from '@/graph/modules/Zoom' | ||
import { Drag } from '@/graph/modules/Drag' | ||
import { defaultConfigValues, defaultScaleToZoom } from '@/graph/variables' | ||
@@ -43,5 +45,7 @@ | ||
private zoomInstance = new Zoom(this.store, this.config) | ||
private dragInstance = new Drag(this.store, this.config) | ||
private fpsMonitor: FPSMonitor | undefined | ||
private hasParticleSystemDestroyed = false | ||
private currentEvent: D3ZoomEvent<HTMLCanvasElement, undefined> | MouseEvent | undefined | ||
private currentEvent: D3ZoomEvent<HTMLCanvasElement, undefined> | D3DragEvent<HTMLCanvasElement, undefined, Hovered> | MouseEvent | undefined | ||
/** | ||
@@ -83,2 +87,3 @@ * The value of `_findHoveredPointExecutionCount` is incremented by 1 on each animation frame. | ||
.on('mouseenter.cosmos', () => { this._isMouseOnCanvas = true }) | ||
.on('mousemove.cosmos', () => { this._isMouseOnCanvas = true }) | ||
.on('mouseleave.cosmos', () => { this._isMouseOnCanvas = false }) | ||
@@ -93,8 +98,25 @@ this.zoomInstance.behavior | ||
.on('end.detect', (e: D3ZoomEvent<HTMLCanvasElement, undefined>) => { this.currentEvent = e }) | ||
this.dragInstance.behavior | ||
.on('start.detect', (e: D3DragEvent<HTMLCanvasElement, undefined, Hovered>) => { | ||
this.currentEvent = e | ||
this.updateCanvasCursor() | ||
}) | ||
.on('drag.detect', (e: D3DragEvent<HTMLCanvasElement, undefined, Hovered>) => { | ||
if (this.dragInstance.isActive) { | ||
this.updateMousePosition(e) | ||
} | ||
this.currentEvent = e | ||
}) | ||
.on('end.detect', (e: D3DragEvent<HTMLCanvasElement, undefined, Hovered>) => { | ||
this.currentEvent = e | ||
this.updateCanvasCursor() | ||
}) | ||
this.canvasD3Selection | ||
.call(this.zoomInstance.behavior) | ||
.call(this.dragInstance.behavior) | ||
.call(this.zoomInstance.behavior) | ||
.on('click', this.onClick.bind(this)) | ||
.on('mousemove', this.onMouseMove.bind(this)) | ||
.on('contextmenu', this.onRightClickMouse.bind(this)) | ||
if (this.config.disableZoom) this.disableZoom() | ||
if (this.config.disableZoom || this.config.disableDrag) this.updateZoomDragBehaviors() | ||
this.setZoomLevel(this.config.initialZoomLevel ?? 1) | ||
@@ -141,2 +163,5 @@ | ||
/** | ||
* Returns the current simulation progress | ||
*/ | ||
public get progress (): number { | ||
@@ -217,8 +242,14 @@ return this.store.simulationProgress | ||
if (prevConfig.disableZoom !== this.config.disableZoom) { | ||
if (this.config.disableZoom) this.disableZoom() | ||
else this.enableZoom() | ||
if (prevConfig.disableZoom !== this.config.disableZoom || prevConfig.disableDrag !== this.config.disableDrag) { | ||
this.updateZoomDragBehaviors() | ||
} | ||
} | ||
/** | ||
* Sets the positions for the graph points. | ||
* | ||
* @param {number[]} pointPositions - An array representing the positions of points in the format [x1, y1, x2, y2, ..., xn, yn], | ||
* where `n` is the index of the point. | ||
* Example: `[1, 2, 3, 4, 5, 6]` sets the first point to (1, 2), the second point to (3, 4), and so on. | ||
*/ | ||
public setPointPositions (pointPositions: number[]): void { | ||
@@ -228,2 +259,9 @@ this.graph.pointPositions = pointPositions | ||
/** | ||
* Sets the colors for the graph points. | ||
* | ||
* @param {number[]} pointColors - An array representing the colors of points in the format [r1, g1, b1, a1, r2, g2, b2, a2, ..., rn, gn, bn, an], | ||
* where each color is represented in RGBA format. | ||
* Example: `[255, 0, 0, 1, 0, 255, 0, 1]` sets the first point to red and the second point to green. | ||
*/ | ||
public setPointColors (pointColors: number[]): void { | ||
@@ -233,2 +271,9 @@ this.graph.inputPointColors = pointColors | ||
/** | ||
* Sets the sizes for the graph points. | ||
* | ||
* @param {number[]} pointSizes - An array representing the sizes of points in the format [size1, size2, ..., sizen], | ||
* where `n` is the index of the point. | ||
* Example: `[10, 20, 30]` sets the first point to size 10, the second point to size 20, and the third point to size 30. | ||
*/ | ||
public setPointSizes (pointSizes: number[]): void { | ||
@@ -238,2 +283,9 @@ this.graph.inputPointSizes = pointSizes | ||
/** | ||
* Sets the links for the graph. | ||
* | ||
* @param {number[]} links - An array representing the links between points in the format [source1, target1, source2, target2, ..., sourcen, targetn], | ||
* where `source` and `target` are the indices of the points being linked. | ||
* Example: `[0, 1, 1, 2]` creates a link from point 0 to point 1 and another link from point 1 to point 2. | ||
*/ | ||
public setLinks (links: number[]): void { | ||
@@ -243,2 +295,9 @@ this.graph.links = links | ||
/** | ||
* Sets the colors for the graph links. | ||
* | ||
* @param {number[]} linkColors - An array representing the colors of links in the format [r1, g1, b1, a1, r2, g2, b2, a2, ..., rn, gn, bn, an], | ||
* where each color is in RGBA format. | ||
* Example: `[255, 0, 0, 1, 0, 255, 0, 1]` sets the first link to red and the second link to green. | ||
*/ | ||
public setLinkColors (linkColors: number[]): void { | ||
@@ -248,2 +307,9 @@ this.graph.inputLinkColors = linkColors | ||
/** | ||
* Sets the widths for the graph links. | ||
* | ||
* @param {number[]} linkWidths - An array representing the widths of links in the format [width1, width2, ..., widthn], | ||
* where `n` is the index of the link. | ||
* Example: `[1, 2, 3]` sets the first link to width 1, the second link to width 2, and the third link to width 3. | ||
*/ | ||
public setLinkWidths (linkWidths: number[]): void { | ||
@@ -253,2 +319,9 @@ this.graph.inputLinkWidths = linkWidths | ||
/** | ||
* Sets the arrows for the graph links. | ||
* | ||
* @param {boolean[]} linkArrows - An array of booleans indicating whether each link should have an arrow, | ||
* in the format [arrow1, arrow2, ..., arrown], where `n` is the index of the link. | ||
* Example: `[true, false, true]` sets arrows on the first and third links, but not on the second link. | ||
*/ | ||
public setLinkArrows (linkArrows: boolean[]): void { | ||
@@ -258,2 +331,18 @@ this.graph.linkArrowsBoolean = linkArrows | ||
/** | ||
* Sets the strength for the graph links. | ||
* | ||
* @param {number[]} linkStrength - An array representing the strength of each link in the format [strength1, strength2, ..., strengthn], | ||
* where `n` is the index of the link. | ||
* Example: `[1, 2, 3]` sets the first link to strength 1, the second link to strength 2, and the third link to strength 3. | ||
*/ | ||
public setLinkStrength (linkStrength: number[]): void { | ||
this.graph.inputLinkStrength = linkStrength | ||
} | ||
/** | ||
* Renders the graph. | ||
* | ||
* @param {boolean} [runSimulation=true] - Optional flag to determine if the simulation should run on render. | ||
*/ | ||
public render (runSimulation = true): void { | ||
@@ -692,3 +781,3 @@ this.graph.update() | ||
this.resizeCanvas() | ||
this.findHoveredPoint() | ||
if (!this.dragInstance.isActive) this.findHoveredPoint() | ||
@@ -735,2 +824,4 @@ if (!disableSimulation) { | ||
if (this.dragInstance.isActive) this.points.drag() | ||
// Clear canvas | ||
@@ -773,6 +864,7 @@ this.reglInstance.clear({ | ||
private updateMousePosition (event: MouseEvent): void { | ||
if (!event || event.offsetX === undefined || event.offsetY === undefined) return | ||
const mouseX = event.offsetX | ||
const mouseY = event.offsetY | ||
private updateMousePosition (event: MouseEvent | D3DragEvent<HTMLCanvasElement, undefined, Hovered>): void { | ||
if (!event) return | ||
const mouseX = (event as MouseEvent).offsetX ?? (event as D3DragEvent<HTMLCanvasElement, undefined, Hovered>).x | ||
const mouseY = (event as MouseEvent).offsetY ?? (event as D3DragEvent<HTMLCanvasElement, undefined, Hovered>).y | ||
if (mouseX === undefined || mouseY === undefined) return | ||
this.store.mousePosition = this.zoomInstance.convertScreenToSpacePosition([mouseX, mouseY]) | ||
@@ -828,10 +920,14 @@ this.store.screenMousePosition = [mouseX, (this.store.screenSize[1] - mouseY)] | ||
private disableZoom (): void { | ||
this.canvasD3Selection | ||
.call(this.zoomInstance.behavior) | ||
.on('wheel.zoom', null) | ||
} | ||
private updateZoomDragBehaviors (): void { | ||
if (this.config.disableDrag) { | ||
this.canvasD3Selection | ||
.call(this.dragInstance.behavior) | ||
.on('.drag', null) | ||
} else this.canvasD3Selection.call(this.dragInstance.behavior) | ||
private enableZoom (): void { | ||
this.canvasD3Selection.call(this.zoomInstance.behavior) | ||
if (this.config.disableZoom) { | ||
this.canvasD3Selection | ||
.call(this.zoomInstance.behavior) | ||
.on('wheel.zoom', null) | ||
} else this.canvasD3Selection.call(this.zoomInstance.behavior) | ||
} | ||
@@ -851,3 +947,2 @@ | ||
const pointSize = pixels[1] as number | ||
const position = [0, 0] as [number, number] | ||
if (pointSize) { | ||
@@ -858,4 +953,2 @@ const hoveredIndex = pixels[0] as number | ||
const pointY = pixels[3] as number | ||
position[0] = pointX | ||
position[1] = pointY | ||
this.store.hoveredPoint = { | ||
@@ -878,5 +971,14 @@ index: hoveredIndex, | ||
if (isMouseout) this.config.events.onPointMouseOut?.(this.currentEvent) | ||
this.updateCanvasCursor() | ||
} | ||
private updateCanvasCursor (): void { | ||
if (this.dragInstance.isActive) select(this.canvas).style('cursor', 'grabbing') | ||
else if (this.store.hoveredPoint) { | ||
if (this.config.disableDrag) select(this.canvas).style('cursor', 'pointer') | ||
else select(this.canvas).style('cursor', 'grab') | ||
} else select(this.canvas).style('cursor', null) | ||
} | ||
} | ||
export type { GraphConfigInterface, GraphEvents, GraphSimulationSettings } from './config' |
@@ -39,3 +39,3 @@ import regl from 'regl' | ||
connectedPointIndices.forEach((connectedPointIndex) => { | ||
connectedPointIndices.forEach(([connectedPointIndex, initialLinkIndex]) => { | ||
this.indices[linkIndex * 4 + 0] = connectedPointIndex % pointsTextureSize | ||
@@ -46,3 +46,3 @@ this.indices[linkIndex * 4 + 1] = Math.floor(connectedPointIndex / pointsTextureSize) | ||
const bias = degree / (degree + connectedDegree) | ||
let strength = 1 / Math.min(degree, connectedDegree) | ||
let strength = data.linkStrength?.[initialLinkIndex] ?? (1 / Math.min(degree, connectedDegree)) | ||
strength = Math.sqrt(strength) | ||
@@ -49,0 +49,0 @@ linkBiasAndStrengthState[linkIndex * 4 + 0] = bias |
@@ -8,2 +8,3 @@ import { getRgbaColor, isNumber } from '@/graph/helper' | ||
public inputLinkWidths: number[] | undefined | ||
public inputLinkStrength: number[] | undefined | ||
@@ -19,5 +20,12 @@ public pointPositions: number[] | undefined | ||
public linkArrows: number[] | undefined | ||
public linkStrength: (number | undefined)[] | undefined | ||
public sourceIndexToTargetIndices: (number[] | undefined)[] | undefined | ||
public targetIndexToSourceIndices: (number[] | undefined)[] | undefined | ||
/** | ||
* Each inner array of `sourceIndexToTargetIndices` and `targetIndexToSourceIndices` contains pairs where: | ||
* - The first value is the target/source index in the node array. | ||
* - The second value is the link index in the array of links. | ||
*/ | ||
public sourceIndexToTargetIndices: ([number, number][] | undefined)[] | undefined | ||
public targetIndexToSourceIndices: ([number, number][] | undefined)[] | undefined | ||
public degree: number[] | undefined | ||
@@ -161,2 +169,14 @@ | ||
public updateLinkStrength (): void { | ||
if (this.linksNumber === undefined) { | ||
this.linkStrength = undefined | ||
} | ||
if (this.inputLinkStrength === undefined || this.inputLinkStrength.length !== this.linksNumber) { | ||
this.linkStrength = undefined | ||
} else { | ||
this.linkStrength = this.inputLinkStrength | ||
} | ||
} | ||
public update (): void { | ||
@@ -169,2 +189,3 @@ this.updatePointColor() | ||
this.updateArrows() | ||
this.updateLinkStrength() | ||
@@ -176,3 +197,3 @@ this._createAdjacencyLists() | ||
public getAdjacentIndices (index: number): number[] | undefined { | ||
return [...(this.sourceIndexToTargetIndices?.[index] || []), ...(this.targetIndexToSourceIndices?.[index] || [])] | ||
return [...(this.sourceIndexToTargetIndices?.[index]?.[0] || []), ...(this.targetIndexToSourceIndices?.[index]?.[0] || [])] | ||
} | ||
@@ -194,6 +215,6 @@ | ||
if (this.sourceIndexToTargetIndices[sourceIndex] === undefined) this.sourceIndexToTargetIndices[sourceIndex] = [] | ||
this.sourceIndexToTargetIndices[sourceIndex]?.push(targetIndex) | ||
this.sourceIndexToTargetIndices[sourceIndex]?.push([targetIndex, i]) | ||
if (this.targetIndexToSourceIndices[targetIndex] === undefined) this.targetIndexToSourceIndices[targetIndex] = [] | ||
this.targetIndexToSourceIndices[targetIndex]?.push(sourceIndex) | ||
this.targetIndexToSourceIndices[targetIndex]?.push([sourceIndex, i]) | ||
} | ||
@@ -200,0 +221,0 @@ } |
@@ -20,2 +20,3 @@ import regl from 'regl' | ||
import trackPositionsFrag from '@/graph/modules/Points/track-positions.frag' | ||
import dragPointFrag from '@/graph/modules/Points/drag-point.frag' | ||
import updateVert from '@/graph/modules/Shared/quad.vert' | ||
@@ -41,2 +42,3 @@ import clearFrag from '@/graph/modules/Shared/clear.frag' | ||
private updatePositionCommand: regl.DrawCommand | undefined | ||
private dragPointCommand: regl.DrawCommand | undefined | ||
private findPointsOnAreaSelectionCommand: regl.DrawCommand | undefined | ||
@@ -72,13 +74,13 @@ private findHoveredPointCommand: regl.DrawCommand | undefined | ||
this.previousPositionFbo = reglInstance.framebuffer({ | ||
color: reglInstance.texture({ | ||
data: initialState, | ||
shape: [pointsTextureSize, pointsTextureSize, 4], | ||
type: 'float', | ||
}), | ||
depth: false, | ||
stencil: false, | ||
}) | ||
if (!this.config.disableSimulation) { | ||
this.previousPositionFbo = reglInstance.framebuffer({ | ||
color: reglInstance.texture({ | ||
data: initialState, | ||
shape: [pointsTextureSize, pointsTextureSize, 4], | ||
type: 'float', | ||
}), | ||
depth: false, | ||
stencil: false, | ||
}) | ||
// Create velocity buffer | ||
@@ -138,2 +140,19 @@ this.velocityFbo = reglInstance.framebuffer({ | ||
} | ||
this.dragPointCommand = reglInstance({ | ||
frag: dragPointFrag, | ||
vert: updateVert, | ||
framebuffer: () => this.currentPositionFbo as regl.Framebuffer2D, | ||
primitive: 'triangle strip', | ||
count: 4, | ||
attributes: { vertexCoord: createQuadBuffer(reglInstance) }, | ||
uniforms: { | ||
positionsTexture: () => this.previousPositionFbo, | ||
mousePos: () => store.mousePosition, | ||
pointsTextureSize: () => store.pointsTextureSize, | ||
dragPointTextureIndex: () => ([ | ||
store.draggingPointIndex !== undefined ? store.draggingPointIndex % store.pointsTextureSize : -1, | ||
store.draggingPointIndex !== undefined ? Math.floor(store.draggingPointIndex / store.pointsTextureSize) : -1, | ||
]), | ||
}, | ||
}) | ||
@@ -413,2 +432,7 @@ this.drawCommand = reglInstance({ | ||
public drag (): void { | ||
this.dragPointCommand?.() | ||
this.swapFbo() | ||
} | ||
public findPointsOnAreaSelection (): void { | ||
@@ -415,0 +439,0 @@ this.findPointsOnAreaSelectionCommand?.() |
@@ -10,3 +10,3 @@ import { scaleLinear } from 'd3-scale' | ||
type Hovered = { index: number; position: [ number, number ] } | ||
export type Hovered = { index: number; position: [ number, number ] } | ||
type Focused = { index: number } | ||
@@ -30,2 +30,3 @@ | ||
public focusedPoint: Focused | undefined = undefined | ||
public draggingPointIndex: number | undefined = undefined | ||
public adjustedSpaceSize = defaultConfigValues.spaceSize | ||
@@ -32,0 +33,0 @@ |
@@ -43,2 +43,3 @@ export const defaultPointColor = '#b3b3b3' | ||
disableZoom: false, | ||
disableDrag: false, | ||
fitViewOnInit: true, | ||
@@ -45,0 +46,0 @@ fitViewDelay: 250, |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
93
9245
1755877
12
28
+ Addedd3-drag@^3.0.0