diff --git a/src/components/graph/graph.js b/src/components/graph/graph.js index 122ca2b6..8a8efd92 100644 --- a/src/components/graph/graph.js +++ b/src/components/graph/graph.js @@ -3,7 +3,7 @@ import React from "react"; import _ from "lodash"; import * as globals from "../../globals"; import styles from "./graph.css"; -import { setupGraphElements } from "./drawGraph"; +import { setupSVGandBrushElements } from "./setupSVGandBrush"; import SectionHeader from "../framework/sectionHeader"; import { connect } from "react-redux"; import actions from "../../actions"; @@ -64,12 +64,6 @@ class Graph extends React.Component { }; } componentDidMount() { - const { svg } = setupGraphElements( - this.handleBrushSelectAction.bind(this), - this.handleBrushDeselectAction.bind(this) - ); - this.setState({ svg }); - // setup canvas and camera const camera = _camera(this.reglCanvas, { scale: true, rotate: false }); const regl = _regl(this.reglCanvas); @@ -111,49 +105,61 @@ class Graph extends React.Component { componentWillReceiveProps(nextProps) { if (this.state.regl && nextProps.vertices) { + /* update regl */ const vertices = nextProps.currentCellSelection; const vertexCount = vertices.length; + const positions = new Float32Array(2 * vertexCount); const colors = new Float32Array(3 * vertexCount); const sizes = new Float32Array(vertexCount); - // Cache a scaled graph - if (!this.scaledGraphVec || this.props.graphVec !== nextProps.graphVec) { - const positions = new Float32Array(2 * vertexCount); - - // d3.scaleLinear().domain([0,1]).range([-1,1]) - const glScaleX = scaleLinear([0, 1], [-1, 1]); - // d3.scaleLinear().domain([0,1]).range([1,-1]) - const glScaleY = scaleLinear([0, 1], [1, -1]); - - const graphVec = nextProps.graphVec; - for (var i = 0; i < vertexCount; i++) { - const cell = vertices[i]; - const cellIdx = cell.__cellIndex__; - - const x = glScaleX(graphVec[2 * cellIdx]); - const y = glScaleY(graphVec[2 * cellIdx + 1]); - positions[2 * i] = x; - positions[2 * i + 1] = y; - } - this.scaledGraphVec = positions; - } + // d3.scaleLinear().domain([0,1]).range([-1,1]) + const glScaleX = scaleLinear([0, 1], [-1, 1]); + // d3.scaleLinear().domain([0,1]).range([1,-1]) + const glScaleY = scaleLinear([0, 1], [1, -1]); /* - Construct Size & Color Vectors + Construct Vectors */ + const graphVec = nextProps.graphVec; for (var i = 0; i < vertexCount; i++) { const cell = vertices[i]; + const cellIdx = cell.__cellIndex__; + const x = glScaleX(graphVec[2 * cellIdx]); + const y = glScaleY(graphVec[2 * cellIdx + 1]); + positions[2 * i] = x; + positions[2 * i + 1] = y; + colors.set(cell.__colorRGB__, 3 * i); + sizes[i] = cell.__selected__ ? 4 : 0.2; /* make this a function of the number of total cells, including regraph */ } - this.state.pointBuffer({ data: this.scaledGraphVec, dimension: 2 }); + this.state.pointBuffer({ data: positions, dimension: 2 }); this.state.colorBuffer({ data: colors, dimension: 3 }); this.state.sizeBuffer({ data: sizes, dimension: 1 }); this.count = vertexCount; } + + if ( + /* invisibly handles the initial null vs integer case as well as resize events */ + nextProps.responsive.height !== this.props.responsive.height || + 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") + .selectAll("*") + .remove(); + const { svg } = setupSVGandBrushElements( + this.handleBrushSelectAction.bind(this), + this.handleBrushDeselectAction.bind(this), + nextProps.responsive, + this.graphPaddingTop + ); + this.setState({ svg }); + } } handleBrushSelectAction() { /* @@ -176,8 +182,12 @@ class Graph extends React.Component { // transform screen coordinates -> cell coordinates const invert = pin => { - const x = 2 * pin[0] / globals.graphWidth - 1; - const y = 2 * (1 - pin[1] / globals.graphHeight) - 1; + 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[12], y + inverse[13]]; return [(pout[0] + 1) / 2, (pout[1] + 1) / 2]; }; diff --git a/src/components/graph/drawGraph.js b/src/components/graph/setupSVGandBrush.js similarity index 58% rename from src/components/graph/drawGraph.js rename to src/components/graph/setupSVGandBrush.js index 647c6315..ec86c587 100644 --- a/src/components/graph/drawGraph.js +++ b/src/components/graph/setupSVGandBrush.js @@ -5,38 +5,39 @@ import * as globals from "../../globals"; /****************************************** ******************************************* - put svg in DOM + put svg & brush in DOM ******************************************* ******************************************/ -export const setupGraphElements = ( +export const setupSVGandBrushElements = ( handleBrushSelectAction, - handleBrushDeselectAction + handleBrushDeselectAction, + responsive, + graphPaddingTop ) => { - var svg = d3 + const side = responsive.height - graphPaddingTop; + const svg = d3 .select("#graphAttachPoint") .append("svg") - .attr("width", globals.graphWidth) - .attr("height", globals.graphHeight) + .attr("width", side) + .attr("height", side) .attr("class", `${styles.graphSVG}`); - setupGraphBrush(svg, handleBrushSelectAction, handleBrushDeselectAction); + svg.append("g").call( + d3 + .brush() + .extent([ + [0, 0], + [ + responsive.height - graphPaddingTop, + responsive.height - graphPaddingTop + ] + ]) + .on("brush", handleBrushSelectAction) + .on("end", handleBrushDeselectAction) + ); return { svg }; }; - -const setupGraphBrush = ( - svg, - handleBrushSelectAction, - handleBrushDeselectAction -) => { - svg.append("g").call( - d3 - .brush() - .extent([[0, 0], [globals.graphWidth, globals.graphHeight]]) - .on("brush", handleBrushSelectAction) - .on("end", handleBrushDeselectAction) - ); -};