Files
cellxgene/client/src/components/graph/overlays/graphOverlayLayer.js
T
Severiano Badajoz 8d725b1ad9 centroid labels (#872)
* refactor reducer to no longer support hover state and hold many labels

* refactor to generate centroidCoordinates for all values of a category

* create hash for function and memoize export

* create button to display all labels for a category

* clear state

* create label for each thing

* calculate on each value

* change to in place modification of map

* switch to for loop with iterator instead of forEach

* use map from centroidLabel instead of creating copy

* adapt for map

* utilize tarrays

* begin documentation

* disable centroids if in zoom mode

* clean up

* persist uncalc coordinates

* document

* clean up and document

* cleanup and document

* fix

* fix undefined labels and document changes

* fix first element skip

* fix conditional recalc

* rename centroidLabel -> centroidLabels

* break out dilation on hover to new reducer

* numerous styling changes for readability

* change centroid icon

* remove colorAccessor from parameters

* recalc centroids on world change

* make label toggle undoable

* remove unused import

* highlight labels on hover

* remove special characters from svg id

* lighten backdrop

* only generate new centroids if they pre-exist

* fix issue with spaces in catagorical value name

* add label buttons to menubar

* change reducer to use colorAccessor and have single toggle

* fix check to see if svg should be rendered

* move svg overlays onto a single svg layer

* dilate on label hover

* remove logs

* allow centroid to update along side regl renders

* allow actions to pass through svg if in zoom mode

* remove artifact from circle

* remove comment

* remove disabling of centroid button

* fix conditional map to screen

* make styling label conditions stricter

* prettier

* refactor onto master

* refactor computePointFlags() to use pointDilation store

* notify when viewport changes

* move svg attributes out of lasso setup and prevent rerenders/writes

* begin playing with transform matrix

* first solution for camera interaction

* create transform using nested groups

* semi-working method using nested groups with transforms

* inversely scale text

* properly do final transform

* cleanup dead / test code

* reinstate original functionality

* breakout centroid labels labels into separate component

* default toggle on for testing

* separate lasso and centroid layers

* remove unnecessary attributes, working hover

* dilation on label hover

* fix dilation on scatterplot

* add dilation on label hover

* break overlay into separate component

* make overlay agnostic to children

* move label mouse actions to centroidlabels component, add overlay state

* remove lasso on switch to camera

* disallow user selection

* fix reducer

* fix subset with continuous color error

* reset labels on color by continuous

* revert centroids on by default

* refactor for nested restructuring

* remove update checking

* remove unused method

* readd deleted hover delay

* remove old centroid setup

* remove centroid from undoable

* cleanup dead code

* remove dead code

* rollback unnecessary changes

* begin adding annotation functionality

* add annotation functionality

* add reset and undo functionality

* change centroids on layout change

* don't create label for unassigned

* add comment pointing out POI for performance

* touch up matrix transform comment

* add comment explaining coordinate space and children's assumed space

* remove dead code

* switch to pure component

* connect centroidLabels to redux

* clean up camera check and null result

* tool tip change

* rename centroid toggle and the like

* fix the misalignment of buttons, also make blueprint use consistent

* fix comment spelling mistakes

* introduce variable for cleaner logic expressions and state assignment

* alter tooltip text to back color by interaction

* remove manual iterator manipulation for forEach()

* remove debounce

* nit fix

* tooltip wording fix

* lint
2020-01-22 13:40:22 -08:00

101 lines
3.0 KiB
JavaScript

import React, { PureComponent, cloneElement } from "react";
import { connect } from "react-redux";
import styles from "../graph.css";
export default
@connect(state => ({
responsive: state.responsive
}))
class GraphOverlayLayer extends PureComponent {
/*
This component takes its children (assumed in the data coordinate space ([0, 1] range, origin in bottom left corner))
and transforms itself multiple times resulting in screen space ([0, screenWidth/Height] range, origin in top left corner)
Children are assigned in the graph component
*/
matrixToTransformString = m => {
/*
Translates the gl-matrix mat3 to SVG matrix transform style
mat3 SVG Transform Function
a c e
b d f / [a, b, 0, c, d, 0, e, f, 1] => matrix(a, b, c, d, e, f) / matrix(sx, 0, 0, sy, tx, ty) / matrix(m[0] m[3] m[1] m[4] m[6] m[7])
0 0 1
*/
return `matrix(${m[0]} ${m[1]} ${m[3]} ${m[4]} ${m[6]} ${m[7]})`;
};
reverseMatrixScaleTransformString = m => {
return `matrix(${1 / m[0]} 0 0 ${1 / m[4]} 0 0)`;
};
render() {
const {
cameraTF,
modelTF,
projectionTF,
responsive,
graphPaddingRightLeft,
graphPaddingTop,
children
} = this.props;
if (!cameraTF) return null;
const inverseTransform = `${this.reverseMatrixScaleTransformString(
modelTF
)} ${this.reverseMatrixScaleTransformString(
cameraTF
)} ${this.reverseMatrixScaleTransformString(
projectionTF
)} scale(1 2) scale(1 ${1 /
-(responsive.height - graphPaddingTop)}) scale(2 1) scale(${1 /
(responsive.width - graphPaddingRightLeft)} 1)`;
const newChildren = React.Children.toArray(children);
return (
<svg
className={styles.graphSVG}
width={responsive.width - graphPaddingRightLeft}
height={responsive.height}
pointerEvents="none"
style={{ zIndex: 99 }}
>
<g
id="canvas-transformation-group-x"
transform={`scale(${responsive.width -
graphPaddingRightLeft} 1) scale(.5 1) translate(1 0)`}
>
<g
id="canvas-transformation-group-y"
transform={`scale(1 ${-(
responsive.height - graphPaddingTop
)}) translate(0 -1) scale(1 .5) translate(0 1)`}
>
<g
id="projection-transformation-group"
transform={this.matrixToTransformString(projectionTF)}
>
<g
id="camera-transformation-group"
transform={this.matrixToTransformString(cameraTF)}
>
<g
id="model-transformation-group"
transform={this.matrixToTransformString(modelTF)}
>
{newChildren.map(child =>
cloneElement(child, { inverseTransform })
)}
</g>
</g>
</g>
</g>
</g>
</svg>
);
}
}