Add frontend

This commit is contained in:
Emanuele Bezzi
2021-12-01 16:49:13 -05:00
parent 54d4de431c
commit db0f50d011
2 changed files with 86 additions and 24 deletions

View File

@@ -0,0 +1,38 @@
export default function drawSpatialImageRegl(regl) {
return regl({
frag: `
precision mediump float;
uniform sampler2D texture;
varying vec2 uv;
void main () {
gl_FragColor = texture2D(texture, uv);
}`,
vert: `
precision mediump float;
attribute vec2 position;
varying vec2 uv;
const float zMiddle = 0.;
uniform mat3 projView;
vec2 norm(vec2 position) {
return ((position - 0.5) * 2.0) * vec2(1., -1.);
}
void main() {
uv = position;
vec3 xy = projView * vec3(norm(position), 1.);
gl_Position = vec4(xy.xy, 0, 1.);
}`,
attributes: {
position: [-1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1],
},
uniforms: {
projView: regl.prop("projView"),
texture: regl.prop("spatialImageAsTexture"),
},
count: 6,
});
}

View File

@@ -14,6 +14,7 @@ import {
createColorTable,
createColorQuery,
} from "../../util/stateManager/colorHelpers";
import _drawSpatialImage from "./drawSpatialImageRegl";
import * as globals from "../../globals";
import GraphOverlayLayer from "./overlays/graphOverlayLayer";
@@ -87,6 +88,7 @@ class Graph extends React.Component {
const camera = _camera(canvas);
const regl = _regl(canvas);
const drawPoints = _drawPoints(regl);
const drawSpatialImage = _drawSpatialImage(regl);
// preallocate webgl buffers
const pointBuffer = regl.buffer();
@@ -100,6 +102,7 @@ class Graph extends React.Component {
pointBuffer,
colorBuffer,
flagBuffer,
drawSpatialImage,
};
}
@@ -232,6 +235,7 @@ class Graph extends React.Component {
pointBuffer: null,
colorBuffer: null,
flagBuffer: null,
drawSpatialImage: null,
// component rendering derived state - these must stay synchronized
// with the reducer state they were generated from.
@@ -317,7 +321,10 @@ class Graph extends React.Component {
if (e.type !== "wheel") e.preventDefault();
if (camera.handleEvent(e, projectionTF)) {
this.renderCanvas();
this.setState((state) => ({ ...state, updateOverlay: !state.updateOverlay }));
this.setState((state) => ({
...state,
updateOverlay: !state.updateOverlay,
}));
}
};
@@ -509,6 +516,13 @@ class Graph extends React.Component {
return { toolSVG: newToolSVG, tool, container };
};
loadTextureFromUrl = (src) => new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
});
fetchAsyncProps = async (props) => {
const {
annoMatrix,
@@ -551,6 +565,10 @@ class Graph extends React.Component {
pointDilationLabel
);
this.spatialImage = await this.loadTextureFromUrl(
"/api/v0.2/spatial/image"
);
const { width, height } = viewport;
return {
positions,
@@ -721,6 +739,7 @@ class Graph extends React.Component {
flagBuffer,
camera,
projectionTF,
drawSpatialImage,
} = this.state;
this.renderPoints(
regl,
@@ -729,7 +748,8 @@ class Graph extends React.Component {
pointBuffer,
flagBuffer,
camera,
projectionTF
projectionTF,
drawSpatialImage
);
});
@@ -797,7 +817,8 @@ class Graph extends React.Component {
pointBuffer,
flagBuffer,
camera,
projectionTF
projectionTF,
drawSpatialImage
) {
const { annoMatrix } = this.props;
if (!this.reglCanvas || !annoMatrix) return;
@@ -809,7 +830,7 @@ class Graph extends React.Component {
regl.poll();
regl.clear({
depth: 1,
color: [1, 1, 1, 1],
color: [0, 0, 0, 0],
});
drawPoints({
distance: camera.distance(),
@@ -821,6 +842,12 @@ class Graph extends React.Component {
nPoints: schema.dataframe.nObs,
minViewportDimension: Math.min(width, height),
});
drawSpatialImage({
projView,
spatialImageAsTexture: regl.texture({
data: this.spatialImage,
}),
});
regl._gl.flush();
}
@@ -951,32 +978,29 @@ const ErrorLoading = ({ displayName, error, width, height }) => {
);
};
const StillLoading = ({ displayName, width, height }) =>
const StillLoading = ({ displayName, width, height }) => (
/*
Render a busy/loading indicator
*/
(
<div
style={{
position: "fixed",
fontWeight: 500,
top: height / 2,
width,
}}
>
<div
style={{
position: "fixed",
fontWeight: 500,
top: height / 2,
width,
display: "flex",
justifyContent: "center",
justifyItems: "center",
alignItems: "center",
}}
>
<div
style={{
display: "flex",
justifyContent: "center",
justifyItems: "center",
alignItems: "center",
}}
>
<Button minimal loading intent="primary" />
<span style={{ fontStyle: "italic" }}>Loading {displayName}</span>
</div>
<Button minimal loading intent="primary" />
<span style={{ fontStyle: "italic" }}>Loading {displayName}</span>
</div>
)
;
</div>
);
export default Graph;