mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-06 10:48:12 +08:00
regl working in browser
This commit is contained in:
@@ -0,0 +1,78 @@
|
|||||||
|
import mat4 from 'gl-mat4';
|
||||||
|
import fit from 'canvas-fit';
|
||||||
|
import _camera from '../../util/camera.js'
|
||||||
|
import _regl from 'regl'
|
||||||
|
import _drawPoints from './drawPointsRegl'
|
||||||
|
|
||||||
|
// setup canvas and camera
|
||||||
|
const canvas = document.body.appendChild(document.createElement('canvas'))
|
||||||
|
console.log('canvas',canvas)
|
||||||
|
// css(canvas, {zIndex: -1000})
|
||||||
|
|
||||||
|
const camera = _camera(canvas, {scale: true, rotate: false});
|
||||||
|
const regl = _regl(canvas)
|
||||||
|
|
||||||
|
window.addEventListener('resize', fit(canvas), false)
|
||||||
|
|
||||||
|
// add explanation
|
||||||
|
const div = document.createElement('h1')
|
||||||
|
// div.innerHTML = 'press spacebar to change'
|
||||||
|
// css(div, {'font-family': 'monospace', 'text-align': 'center'})
|
||||||
|
// document.body.appendChild(div)
|
||||||
|
|
||||||
|
// import draw functions
|
||||||
|
const drawPoints = _drawPoints(regl)
|
||||||
|
|
||||||
|
// import data generators
|
||||||
|
const generatePoints = function (count) {
|
||||||
|
return Array(count).fill().map(function () {
|
||||||
|
return [
|
||||||
|
Math.random() - 0.5,
|
||||||
|
Math.random() - 0.5
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateColors = function (count) {
|
||||||
|
return Array(count).fill().map(function () {
|
||||||
|
return [
|
||||||
|
Math.random(),
|
||||||
|
Math.random(),
|
||||||
|
Math.random()
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// set constants
|
||||||
|
const count = 3e4
|
||||||
|
|
||||||
|
// preallocate buffers
|
||||||
|
const pointBuffer = regl.buffer(count)(generatePoints(count))
|
||||||
|
const colorBuffer = regl.buffer(count)(generateColors(count))
|
||||||
|
|
||||||
|
// update on spacebar
|
||||||
|
document.body.onkeyup = function(e){
|
||||||
|
if (e.keyCode == 32){
|
||||||
|
pointBuffer(generatePoints(count))
|
||||||
|
colorBuffer(generateColors(count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
regl.frame(({viewportWidth, viewportHeight, time}) => {
|
||||||
|
|
||||||
|
regl.clear({
|
||||||
|
depth: 1,
|
||||||
|
color: [1, 1, 1, 1]
|
||||||
|
})
|
||||||
|
|
||||||
|
drawPoints({
|
||||||
|
distance: camera.distance,
|
||||||
|
color: colorBuffer,
|
||||||
|
position: pointBuffer,
|
||||||
|
count: count,
|
||||||
|
view: camera.view(),
|
||||||
|
scale: viewportHeight/viewportWidth
|
||||||
|
})
|
||||||
|
|
||||||
|
camera.tick()
|
||||||
|
})
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
const mat4 = require('gl-mat4')
|
||||||
|
|
||||||
|
export default function (regl) {
|
||||||
|
return regl({
|
||||||
|
vert: `
|
||||||
|
precision mediump float;
|
||||||
|
attribute vec2 position;
|
||||||
|
attribute vec3 color;
|
||||||
|
uniform float distance;
|
||||||
|
uniform mat4 projection, view;
|
||||||
|
varying vec3 fragColor;
|
||||||
|
void main() {
|
||||||
|
gl_PointSize = 30.0 / pow(distance, 2.5);
|
||||||
|
gl_Position = projection * view * vec4(position.x, -position.y, 0, 1);
|
||||||
|
fragColor = color;
|
||||||
|
}`,
|
||||||
|
|
||||||
|
frag: `
|
||||||
|
precision mediump float;
|
||||||
|
varying vec3 fragColor;
|
||||||
|
void main() {
|
||||||
|
if (length(gl_PointCoord.xy - 0.5) > 0.5) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(fragColor, 1);
|
||||||
|
}`,
|
||||||
|
|
||||||
|
attributes: {
|
||||||
|
position: regl.prop('position'),
|
||||||
|
color: regl.prop('color')
|
||||||
|
},
|
||||||
|
|
||||||
|
uniforms: {
|
||||||
|
distance: regl.prop('distance'),
|
||||||
|
view: regl.prop('view'),
|
||||||
|
projection: (context, props) =>
|
||||||
|
mat4.perspective([],
|
||||||
|
Math.PI / 2,
|
||||||
|
context.viewportWidth * props.scale / context.viewportHeight,
|
||||||
|
0.01, 1000),
|
||||||
|
},
|
||||||
|
|
||||||
|
count: regl.prop('count'),
|
||||||
|
|
||||||
|
primitive: 'points'
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import {setupGraphElements, drawGraphUsingRenderQueue} from "./drawGraph";
|
|||||||
import SectionHeader from "../framework/sectionHeader";
|
import SectionHeader from "../framework/sectionHeader";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import actions from "../../actions";
|
import actions from "../../actions";
|
||||||
|
import drawScatterplotRegl from "./drawGraphRegl";
|
||||||
|
|
||||||
@connect((state) => {
|
@connect((state) => {
|
||||||
|
|
||||||
@@ -37,6 +38,36 @@ class Graph extends React.Component {
|
|||||||
brush: null,
|
brush: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
// const {svg, ctx} = setupGraphElements(
|
||||||
|
// this.handleBrushSelectAction.bind(this),
|
||||||
|
// this.handleBrushDeselectAction.bind(this)
|
||||||
|
// );
|
||||||
|
// this.setState({svg, ctx});
|
||||||
|
console.log('div', this.graphAttachPointDiv)
|
||||||
|
}
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
/* maybe should do a check here to confirm ref exists and pass it? */
|
||||||
|
if (
|
||||||
|
this.state.ctx &&
|
||||||
|
nextProps.vertices
|
||||||
|
// nextProps.expressions &&
|
||||||
|
// nextProps.expressionsCountsMap &&
|
||||||
|
) {
|
||||||
|
drawGraphUsingRenderQueue(
|
||||||
|
this.state.ctx,
|
||||||
|
nextProps.expressionsCountsMap,
|
||||||
|
nextProps.colorAccessor,
|
||||||
|
nextProps.ranges, /* assumption that this exists if vertices does both are on cells */
|
||||||
|
nextProps.metadata,
|
||||||
|
nextProps.currentCellSelection,
|
||||||
|
nextProps.graphBrushSelection,
|
||||||
|
nextProps.colorScale,
|
||||||
|
nextProps.graphMap,
|
||||||
|
nextProps.opacityForDeselectedCells,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
handleBrushSelectAction() {
|
handleBrushSelectAction() {
|
||||||
/*
|
/*
|
||||||
No idea why d3 event scope works like this
|
No idea why d3 event scope works like this
|
||||||
@@ -74,38 +105,6 @@ class Graph extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
/* maybe should do a check here to confirm ref exists and pass it? */
|
|
||||||
if (
|
|
||||||
this.state.ctx &&
|
|
||||||
nextProps.vertices
|
|
||||||
// nextProps.expressions &&
|
|
||||||
// nextProps.expressionsCountsMap &&
|
|
||||||
) {
|
|
||||||
|
|
||||||
drawGraphUsingRenderQueue(
|
|
||||||
this.state.ctx,
|
|
||||||
nextProps.expressionsCountsMap,
|
|
||||||
nextProps.colorAccessor,
|
|
||||||
nextProps.ranges, /* assumption that this exists if vertices does both are on cells */
|
|
||||||
nextProps.metadata,
|
|
||||||
nextProps.currentCellSelection,
|
|
||||||
nextProps.graphBrushSelection,
|
|
||||||
nextProps.colorScale,
|
|
||||||
nextProps.graphMap,
|
|
||||||
nextProps.opacityForDeselectedCells,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const {svg, ctx} = setupGraphElements(
|
|
||||||
this.handleBrushSelectAction.bind(this),
|
|
||||||
this.handleBrushDeselectAction.bind(this)
|
|
||||||
);
|
|
||||||
this.setState({svg, ctx});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOpacityRangeChange(e) {
|
handleOpacityRangeChange(e) {
|
||||||
this.props.dispatch({
|
this.props.dispatch({
|
||||||
type: "change opacity deselected cells in 2d graph background",
|
type: "change opacity deselected cells in 2d graph background",
|
||||||
@@ -150,7 +149,10 @@ class Graph extends React.Component {
|
|||||||
step="0.01"
|
step="0.01"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div id="graphAttachPoint"> </div>
|
<div
|
||||||
|
id="graphAttachPoint"
|
||||||
|
ref={(div) => { this.graphAttachPointDiv = div}}>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user