This commit is contained in:
bkmartinjr
2018-05-05 13:15:10 -07:00
parent d91d42f2c4
commit 90c7daf571
62 changed files with 2398 additions and 1912 deletions
+145 -104
View File
@@ -1,29 +1,38 @@
import React from 'react';
// jshint esversion: 6
import React from "react";
import _ from "lodash";
import * as globals from "../../globals";
import styles from "./graph.css";
import {setupGraphElements, drawGraphUsingRenderQueue} from "./drawGraph";
import { setupGraphElements, drawGraphUsingRenderQueue } from "./drawGraph";
import SectionHeader from "../framework/sectionHeader";
import { connect } from "react-redux";
import actions from "../../actions";
import mat4 from 'gl-mat4';
import fit from 'canvas-fit';
import _camera from '../../util/camera.js'
import _regl from 'regl'
import _drawPoints from './drawPointsRegl'
import mat4 from "gl-mat4";
import fit from "canvas-fit";
import _camera from "../../util/camera.js";
import _regl from "regl";
import _drawPoints from "./drawPointsRegl";
import FaCrosshair from 'react-icons/lib/fa/crosshairs';
import FaZoom from 'react-icons/lib/fa/search-plus';
import FaSave from 'react-icons/lib/fa/download';
import FaCrosshair from "react-icons/lib/fa/crosshairs";
import FaZoom from "react-icons/lib/fa/search-plus";
import FaSave from "react-icons/lib/fa/download";
/* https://bl.ocks.org/mbostock/9078690 - quadtree for onClick / hover selections */
@connect((state) => {
const vertices = state.cells.cells && state.cells.cells.data.graph ? state.cells.cells.data.graph : null;
const ranges = state.cells.cells && state.cells.cells.data.ranges ? state.cells.cells.data.ranges : null;
const metadata = state.cells.cells && state.cells.cells.data.metadata ? state.cells.cells.data.metadata : null;
@connect(state => {
const vertices =
state.cells.cells && state.cells.cells.data.graph
? state.cells.cells.data.graph
: null;
const ranges =
state.cells.cells && state.cells.cells.data.ranges
? state.cells.cells.data.ranges
: null;
const metadata =
state.cells.cells && state.cells.cells.data.metadata
? state.cells.cells.data.metadata
: null;
return {
ranges,
@@ -35,11 +44,10 @@ import FaSave from 'react-icons/lib/fa/download';
graphMap: state.controls.graphMap,
currentCellSelection: state.controls.currentCellSelection,
graphBrushSelection: state.controls.graphBrushSelection,
opacityForDeselectedCells: state.controls.opacityForDeselectedCells,
}
opacityForDeselectedCells: state.controls.opacityForDeselectedCells
};
})
class Graph extends React.Component {
constructor(props) {
super(props);
this.count = 0;
@@ -48,35 +56,32 @@ class Graph extends React.Component {
svg: null,
ctx: null,
brush: null,
mode: "brush",
mode: "brush"
};
}
componentDidMount() {
const {
svg
} = setupGraphElements(
const { svg } = setupGraphElements(
this.handleBrushSelectAction.bind(this),
this.handleBrushDeselectAction.bind(this)
);
this.setState({svg});
this.setState({ svg });
// setup canvas and camera
const camera = _camera(this.reglCanvas, {scale: true, rotate: false});
const regl = _regl(this.reglCanvas)
const camera = _camera(this.reglCanvas, { scale: true, rotate: false });
const regl = _regl(this.reglCanvas);
const drawPoints = _drawPoints(regl)
const drawPoints = _drawPoints(regl);
// preallocate buffers
const pointBuffer = regl.buffer();
const colorBuffer = regl.buffer();
const sizeBuffer = regl.buffer();
regl.frame(({viewportWidth, viewportHeight}) => {
regl.frame(({ viewportWidth, viewportHeight }) => {
regl.clear({
depth: 1,
color: [1, 1, 1, 1]
})
});
drawPoints({
size: sizeBuffer,
@@ -86,18 +91,17 @@ class Graph extends React.Component {
count: this.count,
view: camera.view(),
scale: viewportHeight / viewportWidth
})
});
camera.tick()
})
camera.tick();
});
this.setState({
regl,
pointBuffer,
colorBuffer,
sizeBuffer
})
});
}
componentWillReceiveProps(nextProps) {
/* maybe should do a check here to confirm ref exists and pass it? */
@@ -120,12 +124,11 @@ class Graph extends React.Component {
// nextProps.opacityForDeselectedCells,
// )
// }
if (
this.state.regl &&
nextProps.vertices
) {
const _currentCellSelectionMap = _.keyBy(nextProps.currentCellSelection, "CellName"); /* move me to the reducer */
if (this.state.regl && nextProps.vertices) {
const _currentCellSelectionMap = _.keyBy(
nextProps.currentCellSelection,
"CellName"
); /* move me to the reducer */
const positions = [];
positions.length = nextProps.currentCellSelection.length;
@@ -134,33 +137,38 @@ class Graph extends React.Component {
const sizes = [];
sizes.length = nextProps.currentCellSelection.length;
const glScaleX = d3.scaleLinear()
.domain([0,1])
.range([-1, 1]) /* padding */
const glScaleY = d3.scaleLinear()
const glScaleX = d3
.scaleLinear()
.domain([0, 1])
.range([1, -1]) /* padding */
.range([-1, 1]); /* padding */
const glScaleY = d3
.scaleLinear()
.domain([0, 1])
.range([1, -1]); /* padding */
/*
Construct Vectors
*/
_.each(nextProps.currentCellSelection, (cell, i) => {
if (nextProps.graphMap[cell["CellName"]]) { /* fails silently, sometimes this is undefined, in which case the graph array should be shorter than the cell array, check in reducer */
if (nextProps.graphMap[cell["CellName"]]) {
/* fails silently, sometimes this is undefined, in which case the graph array should be shorter than the cell array, check in reducer */
positions[i] = [
glScaleX(nextProps.graphMap[cell["CellName"]][0]),
glScaleY(nextProps.graphMap[cell["CellName"]][1])
]
];
colors[i] = cell.__colorRGB__;
sizes[i] = cell["__selected__"] ? 4 : .2 /* make this a function of the number of total cells, including regraph */
sizes[i] = cell["__selected__"]
? 4
: 0.2; /* make this a function of the number of total cells, including regraph */
}
})
});
this.state.pointBuffer(positions)
this.state.colorBuffer(colors)
this.state.sizeBuffer(sizes)
this.count = positions.length
this.state.pointBuffer(positions);
this.state.colorBuffer(colors);
this.state.sizeBuffer(sizes);
this.count = positions.length;
}
}
handleBrushSelectAction() {
@@ -183,7 +191,7 @@ class Graph extends React.Component {
northwestY: s[0][1],
southeastX: s[1][0],
southeastY: s[1][1]
}
};
brushCoords.dx = brushCoords.southeastX - brushCoords.northwestX;
brushCoords.dy = brushCoords.southeastY - brushCoords.northwestY;
@@ -191,20 +199,20 @@ class Graph extends React.Component {
this.props.dispatch({
type: "graph brush selection change",
brushCoords
})
});
}
handleBrushDeselectAction() {
if (!d3.event.selection) {
this.props.dispatch({
type: "graph brush deselect"
})
});
}
}
handleOpacityRangeChange(e) {
this.props.dispatch({
type: "change opacity deselected cells in 2d graph background",
data: e.target.value
})
});
}
render() {
@@ -212,20 +220,24 @@ class Graph extends React.Component {
<div
id="graphWrapper"
style={{
height: 1050, /* move this to globals */
height: 1050 /* move this to globals */,
backgroundColor: "white",
borderRadius: 3,
boxShadow: "3px 4px 13px 0px rgba(201,201,201,1)",
}}>
boxShadow: "3px 4px 13px 0px rgba(201,201,201,1)"
}}
>
<div
style={{
padding: 10,
display: "flex",
justifyContent: "space-between",
alignItems: "baseline"
}}>
}}
>
<button
onClick={() => { this.props.dispatch(actions.regraph()) }}
onClick={() => {
this.props.dispatch(actions.regraph());
}}
style={{
fontSize: 12,
fontWeight: 400,
@@ -233,67 +245,96 @@ class Graph extends React.Component {
padding: "10px 20px",
backgroundColor: globals.brightBlue,
border: "none",
cursor: "pointer",
cursor: "pointer"
}}
>
Regraph present selection
Regraph present selection
</button>
<div>
<span style={{ marginRight: 10, fontSize: 12}}>
<span style={{ marginRight: 10, fontSize: 12 }}>
deselected opacity
</span>
<input
style={{position: "relative", top: 6, marginRight: 20}}
style={{ position: "relative", top: 6, marginRight: 20 }}
type="range"
onChange={this.handleOpacityRangeChange.bind(this)}
min={0}
max={1}
step="0.01"
/>
<span style={{position: "relative", top: 3}}>
<button
onClick={() => { this.setState({mode: "brush"}) }}
style={{
cursor: "pointer",
border: this.state.mode === "brush" ? "1px solid black" : "1px solid white",
backgroundColor: "white",
padding: 5,
borderRadius: 3
}}> <FaCrosshair/> </button>
<button
onClick={() => { this.setState({mode: "zoom"}) }}
style={{
cursor: "pointer",
border: this.state.mode === "zoom" ? "1px solid black" : "1px solid white",
backgroundColor: "white",
padding: 5,
borderRadius: 3
}}> <FaZoom/> </button>
</span>
/>
<span style={{ position: "relative", top: 3 }}>
<button
onClick={() => {
this.setState({ mode: "brush" });
}}
style={{
cursor: "pointer",
border:
this.state.mode === "brush"
? "1px solid black"
: "1px solid white",
backgroundColor: "white",
padding: 5,
borderRadius: 3
}}
>
{" "}
<FaCrosshair />{" "}
</button>
<button
onClick={() => {
this.setState({ mode: "zoom" });
}}
style={{
cursor: "pointer",
border:
this.state.mode === "zoom"
? "1px solid black"
: "1px solid white",
backgroundColor: "white",
padding: 5,
borderRadius: 3
}}
>
{" "}
<FaZoom />{" "}
</button>
</span>
</div>
<div>
<button style={{
fontSize: 12,
fontWeight: 400,
color: "white",
padding: "10px 20px",
backgroundColor: globals.brightBlue,
border: "none",
cursor: "pointer",
}}> <FaSave style={{display: "inline-block"}}/> csv url for present selection </button>
<button
style={{
fontSize: 12,
fontWeight: 400,
color: "white",
padding: "10px 20px",
backgroundColor: globals.brightBlue,
border: "none",
cursor: "pointer"
}}
>
{" "}
<FaSave style={{ display: "inline-block" }} /> csv url for present
selection{" "}
</button>
</div>
</div>
<div
style={{display: this.state.mode === "brush" ? "inherit" : "none"}}
style={{ display: this.state.mode === "brush" ? "inherit" : "none" }}
id="graphAttachPoint"
>
</div>
<div style={{padding: 0, margin: 0}}>
<canvas width={globals.graphWidth} height={globals.graphHeight} ref={(canvas) => { this.reglCanvas = canvas}}/>
/>
<div style={{ padding: 0, margin: 0 }}>
<canvas
width={globals.graphWidth}
height={globals.graphHeight}
ref={canvas => {
this.reglCanvas = canvas;
}}
/>
</div>
</div>
)
);
}
};
}
export default Graph;