Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Focus view on a node #107

Merged
merged 30 commits into from
Nov 13, 2018
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
bc8cefc
feat: Focus graph on a node
LonelyPrincess Sep 7, 2018
bbcb9c1
feat: Node focus feature example added to sandbox
LonelyPrincess Sep 7, 2018
a1d9268
fix: Ensure that focusZoom is between minZoom and maxZoom
LonelyPrincess Sep 10, 2018
1fdda0d
Merge branch 'master' into feat/focus-on-node
LonelyPrincess Sep 22, 2018
2e9670f
fix: Avoid issue with id datatypes when searching for focused node
LonelyPrincess Sep 22, 2018
bcb1d98
refactor: Improve readability for focusZoom bounds
LonelyPrincess Sep 24, 2018
5103219
refactor: Remove statements in library code
LonelyPrincess Sep 24, 2018
5f6fcd2
revert: Removed blank lines in DOCUMENTATION.md
LonelyPrincess Sep 30, 2018
baf23b5
docs: Added more information on focusZoom property
LonelyPrincess Sep 30, 2018
5b44b36
feat: Customize focus animation length
LonelyPrincess Sep 30, 2018
7be4448
refactor: focusNodeId wrapped in data props
LonelyPrincess Sep 30, 2018
f7d9e69
refactor: focus transformation function moved to graphHelper
LonelyPrincess Sep 30, 2018
b70f016
Merge branch 'master' into feat/focus-on-node
LonelyPrincess Sep 30, 2018
eab8c6f
docs: Updated jsdoc for getCenterAndZoomTransformation
LonelyPrincess Sep 30, 2018
5614c5d
refactor: Renamed config param for focus animation duration
LonelyPrincess Sep 30, 2018
11026db
test: Graph snapshot updated
LonelyPrincess Sep 30, 2018
d596544
Merge branch 'master' into feat/focus-on-node
LonelyPrincess Oct 6, 2018
4cc8ef6
Merge branch 'master' into feat/focus-on-node
LonelyPrincess Oct 16, 2018
918b5cb
fix: Consider hidden links when obtaining matrix
LonelyPrincess Oct 16, 2018
963991b
Merge branch 'master' into feat/focus-on-node
LonelyPrincess Oct 17, 2018
948596c
fix: Reset transition duration after focus animation
LonelyPrincess Oct 22, 2018
701ea49
test: Graph snapshot updated with default transition duration
LonelyPrincess Oct 22, 2018
391b1e0
fix: Drag & drop in focused node
LonelyPrincess Oct 29, 2018
b76d853
refactor: Reset transition duration on drag start
LonelyPrincess Oct 29, 2018
63c92b1
style: Added blank line after variable declaration
LonelyPrincess Oct 29, 2018
aac9946
chore: Browser environment added to ESLint config
LonelyPrincess Oct 29, 2018
c3ed06d
refactor: getCenterAndZoomTransformation receives d3Node object
LonelyPrincess Oct 30, 2018
de9da5f
Merge branch 'master' into feat/focus-on-node
LonelyPrincess Oct 30, 2018
62f6754
fix: Node not centered when focusing with zoom
LonelyPrincess Nov 13, 2018
3e80a5e
refactor: Store focusedNodeId in Graph component state
LonelyPrincess Nov 13, 2018
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
2 changes: 2 additions & 0 deletions docs/DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -811,9 +811,11 @@ components.
},
...
}

LonelyPrincess marked this conversation as resolved.
Show resolved Hide resolved
```

```

* `linkCallbacks` **[Array][81]<[Function][86]>** array of callbacks for used defined event handler for link interactions.
* `config` **[Object][69]** an object containing rd3g consumer defined configurations [config][87] for the graph.
* `highlightedNode` **[string][73]** this value contains a string that represents the some currently highlighted node.
Expand Down
8 changes: 6 additions & 2 deletions sandbox/Sandbox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ export default class Sandbox extends React.Component {
};
}

onClickNode = id => !this.state.config.collapsible && window.alert(`Clicked node ${id}`);
onClickNode = id => {
!this.state.config.collapsible && window.alert(`Clicked node ${id}`);
this.setState({ focusedNodeId: this.state.focusedNodeId !== id ? id : null });
};

onClickLink = (source, target) => window.alert(`Clicked link between ${source} and ${target}`);

Expand Down Expand Up @@ -298,7 +301,8 @@ export default class Sandbox extends React.Component {
onMouseOverNode: this.onMouseOverNode,
onMouseOutNode: this.onMouseOutNode,
onMouseOverLink: this.onMouseOverLink,
onMouseOutLink: this.onMouseOutLink
onMouseOutLink: this.onMouseOutLink,
focusedNodeId: this.state.focusedNodeId
LonelyPrincess marked this conversation as resolved.
Show resolved Hide resolved
};

if (this.state.fullscreen) {
Expand Down
31 changes: 30 additions & 1 deletion src/components/graph/Graph.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,29 @@ export default class Graph extends React.Component {
this.props.onClickNode && this.props.onClickNode(clickedNodeId);
};

/**
* Returns the transformation to apply in order to center the graph on the
* selected node.
* @param {number} nodeId - node to focus the graph view on.
* @returns {string} transform rule to apply.
*/
getCenterAndZoomTransformation = nodeId => {
LonelyPrincess marked this conversation as resolved.
Show resolved Hide resolved
const node = this.state.d3Nodes.find(node => node.id.toString() === nodeId.toString());
LonelyPrincess marked this conversation as resolved.
Show resolved Hide resolved

// If node with specified id doesn't exist, don't do anything
LonelyPrincess marked this conversation as resolved.
Show resolved Hide resolved
if (!node) {
return;
}

const { width, height, focusZoom } = this.state.config;

return `
translate(${width / 2}, ${height / 2})
scale(${focusZoom})
translate(${-node.x}, ${-node.y})
`;
};

render() {
const { nodes, links } = graphRenderer.buildGraph(
this.state.nodes,
Expand All @@ -398,10 +421,16 @@ export default class Graph extends React.Component {
width: this.state.config.width
};

const { focusedNodeId } = this.props;
const containerProps = {
LonelyPrincess marked this conversation as resolved.
Show resolved Hide resolved
style: { transitionDuration: '.75s' },
LonelyPrincess marked this conversation as resolved.
Show resolved Hide resolved
transform: focusedNodeId ? this.getCenterAndZoomTransformation(focusedNodeId) : null
};

return (
<div id={`${this.state.id}-${CONST.GRAPH_WRAPPER_ID}`}>
<svg style={svgStyle}>
<g id={`${this.state.id}-${CONST.GRAPH_CONTAINER_ID}`}>
<g id={`${this.state.id}-${CONST.GRAPH_CONTAINER_ID}`} {...containerProps}>
{links}
{nodes}
</g>
Expand Down
2 changes: 2 additions & 0 deletions src/components/graph/graph.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
* the value the more the less highlighted nodes will be visible (related to *nodeHighlightBehavior*).
* @param {number} [maxZoom=8] - max zoom that can be performed against the graph.
* @param {number} [minZoom=0.1] - min zoom that can be performed against the graph.
* @param {number} [focusZoom=1] - zoom that will be applied when the graph view is focused in a node.
LonelyPrincess marked this conversation as resolved.
Show resolved Hide resolved
* @param {boolean} [panAndZoom=false] - 🚅🚅🚅 pan and zoom effect when performing zoom in the graph,
* a similar functionality may be consulted {@link https://bl.ocks.org/mbostock/2a39a768b1d4bc00a09650edef75ad39|here}.
* @param {boolean} [staticGraph=false] - when setting this value to true the graph will be completely static, thus
Expand Down Expand Up @@ -163,6 +164,7 @@ export default {
linkHighlightBehavior: false,
maxZoom: 8,
minZoom: 0.1,
focusZoom: 1,
nodeHighlightBehavior: false,
panAndZoom: false,
staticGraph: false,
Expand Down
9 changes: 9 additions & 0 deletions src/components/graph/graph.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,15 @@ function initializeGraphState({ data, id, config }, state) {
const formatedId = id.replace(/ /g, '_');
const simulation = _createForceSimulation(newConfig.width, newConfig.height, newConfig.d3 && newConfig.d3.gravity);

// ensure focus zoom is between minZoom and maxZoom
LonelyPrincess marked this conversation as resolved.
Show resolved Hide resolved
const { minZoom, maxZoom, focusZoom } = newConfig;

if (focusZoom > maxZoom) {
newConfig.focusZoom = maxZoom;
} else if (focusZoom < minZoom) {
newConfig.focusZoom = minZoom;
}

return {
id: formatedId,
config: newConfig,
Expand Down