From e83c0da0cf3e932781db31947b2edd9b8241a95d Mon Sep 17 00:00:00 2001 From: stetho Date: Sun, 8 Mar 2020 17:15:40 +0100 Subject: [PATCH 1/2] fix(forcedirected.js): make force directed graph zoomable and pannable fix #7246 --- .../src/ForceDirected.js | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/packages/superset-ui-legacy-plugin-chart-force-directed/src/ForceDirected.js b/packages/superset-ui-legacy-plugin-chart-force-directed/src/ForceDirected.js index ea0dcbada..2f1a895d1 100644 --- a/packages/superset-ui-legacy-plugin-chart-force-directed/src/ForceDirected.js +++ b/packages/superset-ui-legacy-plugin-chart-force-directed/src/ForceDirected.js @@ -38,11 +38,18 @@ const propTypes = { /* Modified from http://bl.ocks.org/d3noob/5141278 */ function ForceDirected(element, props) { const { data, width, height, linkLength = 200, charge = -500 } = props; + + let w = window.innerWidth; + let h = window.innerHeight; + const minZoom = 0.1; + const maxZoom = 7; const div = d3.select(element); + const zoom = d3.behavior.zoom().scaleExtent([minZoom, maxZoom]); div.classed('superset-legacy-chart-force-directed', true); const links = data; const nodes = {}; + // Compute the distinct nodes from the links. links.forEach(link => { link.source = @@ -82,6 +89,9 @@ function ForceDirected(element, props) { nodes[targetName].total += link.value; }); + div.selectAll('*').remove(); + const svg = div.append('svg'); + const g = svg.append('g'); /* eslint-disable no-use-before-define */ // add the curvy lines function tick() { @@ -107,15 +117,22 @@ function ForceDirected(element, props) { .on('tick', tick) .start(); - div.selectAll('*').remove(); - const svg = div - .append('svg') - .attr('width', width) - .attr('height', height); + function resize() { + const { innerWidth, innerHeight } = window; + svg.attr('width', innerWidth).attr('height', innerHeight); + + force + .size([ + force.size()[0] + (innerWidth - w) / zoom.scale(), + force.size()[1] + (innerHeight - h) / zoom.scale(), + ]) + .resume(); + w = innerWidth; + h = innerHeight; + } // build the arrow. - svg - .append('svg:defs') + g.append('svg:defs') .selectAll('marker') .data(['end']) // Different link/path types can be defined here .enter() @@ -132,7 +149,7 @@ function ForceDirected(element, props) { const edgeScale = d3.scale.linear().range([0.1, 0.5]); // add the links and the arrows - const path = svg + const path = g .append('svg:g') .selectAll('path') .data(force.links()) @@ -143,7 +160,7 @@ function ForceDirected(element, props) { .attr('marker-end', 'url(#end)'); // define the nodes - const node = svg + const node = g .selectAll('.node') .data(force.nodes()) .enter() @@ -170,6 +187,9 @@ function ForceDirected(element, props) { .transition() .style('font-size', 12); }) + .on('mousedown', function() { + d3.event.stopPropagation(); + }) .call(force.drag); // add the nodes @@ -187,6 +207,11 @@ function ForceDirected(element, props) { .attr('x', 6) .attr('dy', '.35em') .text(d => d.name); + zoom.on('zoom', function() { + g.attr('transform', `translate(${d3.event.translate})scale(${d3.event.scale})`); + }); + svg.call(zoom); + resize(); } ForceDirected.displayName = 'ForceDirected'; From d7ba315d6b3f6a48290c7fe38f6c222cfc092130 Mon Sep 17 00:00:00 2001 From: stetho Date: Mon, 9 Mar 2020 20:52:21 +0100 Subject: [PATCH 2/2] fix(forcedirected.js): size of the graph computed from props fix #7246 --- .../src/ForceDirected.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/superset-ui-legacy-plugin-chart-force-directed/src/ForceDirected.js b/packages/superset-ui-legacy-plugin-chart-force-directed/src/ForceDirected.js index 2f1a895d1..dc7857727 100644 --- a/packages/superset-ui-legacy-plugin-chart-force-directed/src/ForceDirected.js +++ b/packages/superset-ui-legacy-plugin-chart-force-directed/src/ForceDirected.js @@ -37,10 +37,9 @@ const propTypes = { /* Modified from http://bl.ocks.org/d3noob/5141278 */ function ForceDirected(element, props) { - const { data, width, height, linkLength = 200, charge = -500 } = props; + const { data, linkLength = 200, charge = -500 } = props; + let { width, height } = props; - let w = window.innerWidth; - let h = window.innerHeight; const minZoom = 0.1; const maxZoom = 7; const div = d3.select(element); @@ -123,12 +122,12 @@ function ForceDirected(element, props) { force .size([ - force.size()[0] + (innerWidth - w) / zoom.scale(), - force.size()[1] + (innerHeight - h) / zoom.scale(), + force.size()[0] + (innerWidth - width) / zoom.scale(), + force.size()[1] + (innerHeight - height) / zoom.scale(), ]) .resume(); - w = innerWidth; - h = innerHeight; + width = innerWidth; + height = innerHeight; } // build the arrow.