Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions src/components/graph/Graph.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
getCenterAndZoomTransformation,
initializeGraphState,
initializeNodes,
isPositionInBounds,
} from "./graph.helper";
import { renderGraph } from "./graph.renderer";
import { merge, debounce, throwErr } from "../../utils";
Expand Down Expand Up @@ -235,14 +236,20 @@ export default class Graph extends React.Component {
draggedNode.oldX = draggedNode.x;
draggedNode.oldY = draggedNode.y;

draggedNode.x += d3Event.dx;
draggedNode.y += d3Event.dy;
const newX = draggedNode.x + d3Event.dx;
const newY = draggedNode.y + d3Event.dy;
const shouldUpdateNode = !this.state.config.bounded || isPositionInBounds({ x: newX, y: newY }, this.state);

// set nodes fixing coords fx and fy
draggedNode["fx"] = draggedNode.x;
draggedNode["fy"] = draggedNode.y;
if (shouldUpdateNode) {
draggedNode.x = newX;
draggedNode.y = newY;

this._tick({ draggedNode });
// set nodes fixing coords fx and fy
draggedNode["fx"] = draggedNode.x;
draggedNode["fy"] = draggedNode.y;

this._tick({ draggedNode });
}
}
};

Expand Down Expand Up @@ -310,10 +317,10 @@ export default class Graph extends React.Component {

d3SelectAll(`#${this.state.id}-${CONST.GRAPH_CONTAINER_ID}`).attr("transform", transform);

this.state.config.panAndZoom && this.setState({ transform: transform.k });
this.setState({ transform });

// only send zoom change events if the zoom has changed (_zoomed() also gets called when panning)
if (this.debouncedOnZoomChange && this.state.previousZoom !== transform.k) {
if (this.debouncedOnZoomChange && this.state.previousZoom !== transform.k && !this.state.config.panAndZoom) {
this.debouncedOnZoomChange(this.state.previousZoom, transform.k);
this.setState({ previousZoom: transform.k });
}
Expand Down Expand Up @@ -543,7 +550,8 @@ export default class Graph extends React.Component {
// in order to properly update graph data we need to pause eventual d3 ongoing animations
newGraphElements && this.pauseSimulation();

const transform = newConfig.panAndZoom !== this.state.config.panAndZoom ? 1 : this.state.transform;
const transform =
newConfig.panAndZoom !== this.state.config.panAndZoom ? { x: 0, y: 0, k: 1 } : this.state.transform;
const focusedNodeId = nextProps.data.focusedNodeId;
const d3FocusedNode = this.state.d3Nodes.find(node => `${node.id}` === `${focusedNodeId}`);
const focusTransformation = getCenterAndZoomTransformation(d3FocusedNode, this.state.config);
Expand Down Expand Up @@ -638,7 +646,7 @@ export default class Graph extends React.Component {
this.state.config,
this.state.highlightedNode,
this.state.highlightedLink,
this.state.transform
this.state.transform.k
);

const svgStyle = {
Expand Down
3 changes: 3 additions & 0 deletions src/components/graph/graph.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
* @param {boolean} [staticGraphWithDragAndDrop] - <a id="static-graph-with-drag-and-drop" href="#static-graph-with-drag-and-drop">🔗</a> exactly the same as above <code>staticGraph</code>, but it will allow users to drag&drop nodes.
* <b>Note</b>: If <code>staticGraph</code> is set to <code>true</code>, then <code>staticGraphWithDragAndDrop</code> will not produce the desired behaviour, make sure
* to set only one of them to <code>true</code>.
* @param {boolean} [bounded=false] - <a id="bounded" href="#bounded">🔗</a> if the graph is set as bounded, it will be impossible
* to drag nodes outside the viewport. It does not apply to moving the entire graph around or when zooming in or out.
* @param {number} [width=800] - <a id="width" href="#width">🔗</a> the width of the (svg) area where the graph will be rendered.
* </br>
* @param {Object} d3 d3 object is explained in next section. ⬇️
Expand Down Expand Up @@ -256,6 +258,7 @@ export default {
panAndZoom: false,
staticGraph: false,
staticGraphWithDragAndDrop: false,
bounded: false,
width: 800,
d3: {
alphaTarget: 0.05,
Expand Down
20 changes: 19 additions & 1 deletion src/components/graph/graph.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ function initializeGraphState({ data, id, config }, state) {
simulation,
newGraphElements: false,
configUpdated: false,
transform: 1,
transform: { x: 0, y: 0, k: 1 },
draggedNode: null,
};
}
Expand Down Expand Up @@ -553,6 +553,23 @@ function getNormalizedNodeCoordinates(
return { sourceCoords: { x: x1, y: y1 }, targetCoords: { x: x2, y: y2 } };
}

/**
* Checks if the position is inside the viewport bounds
* @param {{x: number, y: number}} position node's position
* @param {Object} currentState - the current state of the graph.
* @returns {boolean} true if the position is inside the viewport else false
*/
function isPositionInBounds(position, currentState) {
const { transform, config } = currentState;
const invertTransformZoom = 1 / transform.k;
return (
position.x > -transform.x * invertTransformZoom &&
position.x < (config.width - transform.x) * invertTransformZoom &&
position.y > -transform.y * invertTransformZoom &&
position.y < (config.height - transform.y) * invertTransformZoom
);
}

export {
checkForGraphConfigChanges,
checkForGraphElementsChanges,
Expand All @@ -562,4 +579,5 @@ export {
updateNodeHighlightedValue,
getNormalizedNodeCoordinates,
initializeNodes,
isPositionInBounds,
};
2 changes: 1 addition & 1 deletion test/graph/graph.helper.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ describe("Graph Helper", () => {
simulation: {
force: forceStub,
},
transform: 1,
transform: { x: 0, y: 0, k: 1 },
draggedNode: null,
});
});
Expand Down