Merge pull request #107 from chanzuckerberg/freeman-lab/brush-zoom-fix

Fix zooming selection
This commit is contained in:
Colin Megill
2018-06-28 01:24:34 -04:00
committed by GitHub
2 changed files with 61 additions and 43 deletions
+24 -8
View File
@@ -164,20 +164,21 @@ class Graph extends React.Component {
nextProps.responsive.width !== this.props.responsive.width nextProps.responsive.width !== this.props.responsive.width
) { ) {
/* clear out whatever was on the div, even if nothing, but usually the brushes etc */ /* clear out whatever was on the div, even if nothing, but usually the brushes etc */
d3 d3.select("#graphAttachPoint")
.select("#graphAttachPoint")
.selectAll("*") .selectAll("*")
.remove(); .remove();
const { svg } = setupSVGandBrushElements( const { svg, brush, brushContainer } = setupSVGandBrushElements(
this.handleBrushSelectAction.bind(this), this.handleBrushSelectAction.bind(this),
this.handleBrushDeselectAction.bind(this), this.handleBrushDeselectAction.bind(this),
nextProps.responsive, nextProps.responsive,
this.graphPaddingTop this.graphPaddingTop
); );
this.setState({ svg }); this.setState({ svg, brush, brushContainer });
} }
} }
handleBrushSelectAction() { handleBrushSelectAction() {
/* This conditional handles procedural brush deselect. Brush emits an event on procedural deselect because it is move: null */
if (d3.event.sourceEvent !== null) {
/* /*
No idea why d3 event scope works like this No idea why d3 event scope works like this
but apparently but apparently
@@ -199,12 +200,17 @@ class Graph extends React.Component {
// transform screen coordinates -> cell coordinates // transform screen coordinates -> cell coordinates
const invert = pin => { const invert = pin => {
const x = const x =
2 * pin[0] / (this.props.responsive.height - this.graphPaddingTop) - 1; (2 * pin[0]) / (this.props.responsive.height - this.graphPaddingTop) -
1;
const y = const y =
2 * 2 *
(1 - pin[1] / (this.props.responsive.height - this.graphPaddingTop)) - (1 -
pin[1] / (this.props.responsive.height - this.graphPaddingTop)) -
1; 1;
const pout = [x * inverse[14] + inverse[12], y * inverse[14] + inverse[13]]; const pout = [
x * inverse[14] + inverse[12],
y * inverse[14] + inverse[13]
];
return [(pout[0] + 1) / 2, (pout[1] + 1) / 2]; return [(pout[0] + 1) / 2, (pout[1] + 1) / 2];
}; };
@@ -218,8 +224,17 @@ class Graph extends React.Component {
brushCoords brushCoords
}); });
} }
}
handleBrushDeselectAction() { 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({ this.props.dispatch({
type: "graph brush deselect" type: "graph brush deselect"
}); });
@@ -302,6 +317,7 @@ class Graph extends React.Component {
</button> </button>
<button <button
onClick={() => { onClick={() => {
this.handleBrushDeselectAction();
this.setState({ mode: "zoom" }); this.setState({ mode: "zoom" });
}} }}
style={{ style={{
+11 -9
View File
@@ -23,21 +23,23 @@ export const setupSVGandBrushElements = (
.attr("height", side) .attr("height", side)
.attr("class", `${styles.graphSVG}`); .attr("class", `${styles.graphSVG}`);
svg.append("g").call( const brush = d3
d3
.brush() .brush()
.extent([ .extent([
[0, 0], [0, 0],
[ [responsive.height - graphPaddingTop, responsive.height - graphPaddingTop]
responsive.height - graphPaddingTop,
responsive.height - graphPaddingTop
]
]) ])
.on("brush", handleBrushSelectAction) .on("brush", handleBrushSelectAction)
.on("end", handleBrushDeselectAction) .on("end", handleBrushDeselectAction);
);
const brushContainer = svg
.append("g")
.attr("class", "graph_brush")
.call(brush);
return { return {
svg svg,
brushContainer,
brush
}; };
}; };