From 64223ff95e2a780247736eb540798893ed3cfb27 Mon Sep 17 00:00:00 2001 From: Colin Megill Date: Thu, 28 Jun 2018 01:10:05 -0400 Subject: [PATCH 1/3] return brush independently from container --- src/components/graph/setupSVGandBrush.js | 30 +++++++++++++----------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/components/graph/setupSVGandBrush.js b/src/components/graph/setupSVGandBrush.js index ec86c587..3234748b 100644 --- a/src/components/graph/setupSVGandBrush.js +++ b/src/components/graph/setupSVGandBrush.js @@ -23,21 +23,23 @@ export const setupSVGandBrushElements = ( .attr("height", side) .attr("class", `${styles.graphSVG}`); - svg.append("g").call( - d3 - .brush() - .extent([ - [0, 0], - [ - responsive.height - graphPaddingTop, - responsive.height - graphPaddingTop - ] - ]) - .on("brush", handleBrushSelectAction) - .on("end", handleBrushDeselectAction) - ); + const brush = d3 + .brush() + .extent([ + [0, 0], + [responsive.height - graphPaddingTop, responsive.height - graphPaddingTop] + ]) + .on("brush", handleBrushSelectAction) + .on("end", handleBrushDeselectAction); + + const brushContainer = svg + .append("g") + .attr("class", "graph_brush") + .call(brush); return { - svg + svg, + brushContainer, + brush }; }; From b24b71692cf8b6068cdfe40e1bf56d118456e324 Mon Sep 17 00:00:00 2001 From: Colin Megill Date: Thu, 28 Jun 2018 01:10:29 -0400 Subject: [PATCH 2/3] brush on zoom procedural deselect --- src/components/graph/graph.js | 74 +++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/src/components/graph/graph.js b/src/components/graph/graph.js index aa4b5fcb..8df6fcfb 100644 --- a/src/components/graph/graph.js +++ b/src/components/graph/graph.js @@ -164,28 +164,29 @@ class Graph extends React.Component { nextProps.responsive.width !== this.props.responsive.width ) { /* clear out whatever was on the div, even if nothing, but usually the brushes etc */ - d3 - .select("#graphAttachPoint") + d3.select("#graphAttachPoint") .selectAll("*") .remove(); - const { svg } = setupSVGandBrushElements( + const { svg, brush, brushContainer } = setupSVGandBrushElements( this.handleBrushSelectAction.bind(this), this.handleBrushDeselectAction.bind(this), nextProps.responsive, this.graphPaddingTop ); - this.setState({ svg }); + this.setState({ svg, brush, brushContainer }); } } handleBrushSelectAction() { - /* + /* This conditional handles procedural brush deselect. Brush emits an event on procedural deselect because it is move: null */ + if (d3.event.selection) { + /* No idea why d3 event scope works like this but apparently it does https://bl.ocks.org/EfratVil/0e542f5fc426065dd1d4b6daaa345a9f */ - const s = d3.event.selection; - /* + const s = d3.event.selection; + /* event describing brush position: @-------| | | @@ -193,33 +194,47 @@ class Graph extends React.Component { |-------@ */ - // compute inverse view matrix - const inverse = mat4.invert([], this.state.camera.view()); + // compute inverse view matrix + const inverse = mat4.invert([], this.state.camera.view()); - // transform screen coordinates -> cell coordinates - const invert = pin => { - const x = - 2 * pin[0] / (this.props.responsive.height - this.graphPaddingTop) - 1; - const y = - 2 * - (1 - pin[1] / (this.props.responsive.height - this.graphPaddingTop)) - - 1; - const pout = [x * inverse[14] + inverse[12], y * inverse[14] + inverse[13]]; - return [(pout[0] + 1) / 2, (pout[1] + 1) / 2]; - }; + // transform screen coordinates -> cell coordinates + const invert = pin => { + const x = + (2 * pin[0]) / (this.props.responsive.height - this.graphPaddingTop) - + 1; + const y = + 2 * + (1 - + pin[1] / (this.props.responsive.height - this.graphPaddingTop)) - + 1; + const pout = [ + x * inverse[14] + inverse[12], + y * inverse[14] + inverse[13] + ]; + return [(pout[0] + 1) / 2, (pout[1] + 1) / 2]; + }; - const brushCoords = { - northwest: invert([s[0][0], s[0][1]]), - southeast: invert([s[1][0], s[1][1]]) - }; + const brushCoords = { + northwest: invert([s[0][0], s[0][1]]), + southeast: invert([s[1][0], s[1][1]]) + }; - this.props.dispatch({ - type: "graph brush selection change", - brushCoords - }); + this.props.dispatch({ + type: "graph brush selection change", + brushCoords + }); + } } handleBrushDeselectAction() { - if (!d3.event.selection) { + if (d3.event && !d3.event.selection) { + this.props.dispatch({ + type: "graph brush deselect" + }); + } + + if (!d3.event) { + /* this line clears the brush procedurally, ie., zoom button clicked, not a click away from brush on svg */ + this.state.svg.select(".graph_brush").call(this.state.brush.move, null); this.props.dispatch({ type: "graph brush deselect" }); @@ -302,6 +317,7 @@ class Graph extends React.Component {