Public
Edited
Nov 6
1 fork
1 star
Insert cell
Insert cell
Insert cell
container = html `<div style="height:450px;"></div>`
Insert cell
Insert cell
transitions = ({
getPosition: {
duration: 3000,
easing: d3.easeCubic
}
})
Insert cell
// have deck.gl animate
function apply_map_morph(d){
var inst_x
var inst_y
if (map_type === 'Spatial'){
inst_x = d['x']
inst_y = d['y']
} else {
inst_x = d['umap-x']
inst_y = d['umap-y']
}
return [inst_x, inst_y]
}
Insert cell
Insert cell
scatter_inst = {

const {Layer} = deck;
class ScatterInstanced extends Layer {
initializeState() {
const {gl} = this.context;

// Register attributes
this.getAttributeManager().addInstanced({
instancePositions: {
size: 3,
type: gl.DOUBLE,
// adding from here
// https://github.com/visgl/deck.gl/discussions/8118
// https://github.com/visgl/deck.gl/blob/8.9-release/modules/layers/src/scatterplot-layer/scatterplot-layer.ts#L193
transition: true,
accessor: 'getPosition'
},
instanceRadius: {
size: 1,
transition: true,
accessor: 'getRadius',
defaultValue: 1
},
instanceColors: {
size: 4,
normalized: true,
type: gl.UNSIGNED_BYTE,
transition: true,
accessor: 'getColor',
defaultValue: [0, 0, 0, 255],
},
// createing a picking color attribute
customPickingColors: {
size: 3,
type: gl.UNSIGNED_BYTE,
update: this.calculatePickingColors,
}
});
// Save the model in layer state
this.setState({
model: getModel(gl)
});
}
// updateState() {
// }

calculatePickingColors(attribute) {
const {data} = this.props;
const {value, size} = attribute;
let i = 0;

let index = 0;
for (const object of data) {
// Use the index index instead of object.id
const pickingColor = this.encodePickingColor(index);
value[index * 3] = pickingColor[0];
value[index * 3 + 1] = pickingColor[1];
value[index * 3 + 2] = pickingColor[2];
index++;
}
}
}
ScatterInstanced.layerName = 'ScatterInstanced';
ScatterInstanced.defaultProps = defaultProps;

const layer = new ScatterInstanced({
id: `scatterplot-${Date.now()}`,
data: data_inst,
// getPosition: d => d.position,
getPosition: apply_map_morph,
getRadius: d => 10,
getColor: getFillColor,
pickable: true,
updateTriggers: {
getPosition: map_type,
},
transitions: transitions,
onClick: (info, event) => {
console.log('clicking!!!')
}
});
return layer;
}
Insert cell
scatter_norm = new deck.ScatterplotLayer({
id: 'cell_layer',
// data: cell_data,
data: data_norm,
getPosition: apply_map_morph,

getFillColor: getFillColor,
getRadius: 10,
pickable: true,
highlightColor: d => [50, 50, 50],
radiusMinPixels: 10,
opacity: 1,
updateTriggers: {
getPosition: map_type,
},
transitions: transitions,
onClick: (info, event) => {
console.log('clicking regular scatterplot')
}
})
Insert cell
Insert cell
deckgl = {
console.log('--- deckgl\n----------')
var deckgl = new deck.DeckGL({
container,
width: '800px',
height: '800px',
top: '175px',
views:[view],
initialViewState: initial_view_state,
controller: {doubleClickZoom: false},
getTooltip: ({object}) => object && {
html: `${object['leiden']}`,
style: {
fontSize: '0.8em',
padding: '5px',
}
},
});

return deckgl
}
Insert cell
initial_view_state = ({
target: [0, 50, 0],
zoom: 2,
minZoom: -2
})
Insert cell
deckgl.setProps({layers: [scatter_inst, scatter_norm]});
Insert cell
view = new deck.OrthographicView({id: 'ortho'})
Insert cell
data_inst = ([
{name: 'dog', 'x': 1, 'y': 1, 'leiden': "dog", 'umap-x': 1, 'umap-y': 1},
{name: 'elephant', 'x': 20, 'y': 20, 'leiden': "elephant", 'umap-x': -20, 'umap-y': -20}
])
Insert cell
data_norm = ([
{name: 'dog', 'x': 50, 'y': 1, 'leiden': "cat", 'umap-x': 51, 'umap-y': 1},
{name: 'elephant', 'x': 70, 'y': 20, 'leiden': "bird", 'umap-x': 30, 'umap-y': -20}
])
Insert cell
cat_colors = ({dog: 'blue', elephant: 'red', cat: 'yellow', bird: 'black'})
Insert cell
getFillColor = (d) => {
var rgb = d3.color(cat_colors[d['leiden']])
var inst_color = [rgb.r, rgb.g, rgb.b, 255]
return inst_color
}
Insert cell
Insert cell
defaultProps = {
return {
// Center of each circle, in [longitude, latitude, (z)]
getPosition: {type: 'accessor', value: x => x.position},
getColor: {type: 'accessor', value: [0, 0, 0, 255]},
getRadius: {type: 'accessor', value: 1},
}
}
Insert cell
vertexShader = `
attribute vec3 positions;
attribute vec3 instancePositions;
attribute vec3 instancePositions64Low;
attribute float instanceRadius;
attribute vec4 instanceColors;

varying vec4 vColor;
varying vec2 vPosition;

attribute vec3 customPickingColors;

void main(void) {
vec3 offsetCommon = positions * project_size(instanceRadius);
vec3 positionCommon = project_position(instancePositions, instancePositions64Low);
gl_Position = project_common_position_to_clipspace(vec4(positionCommon + offsetCommon, 1.0));

vPosition = positions.xy;
vColor = instanceColors;

picking_setPickingColor(customPickingColors);
}`


Insert cell
fragmentShader = `
precision highp float;

varying vec4 vColor;
varying vec2 vPosition;

void main(void) {
float distToCenter = length(vPosition);

if (distToCenter > 1.0) {
discard;
}

gl_FragColor = vec4(vColor.rgb, vColor.a);

// Should be the last Fragment shader instruction that updates gl_FragColor
gl_FragColor = picking_filterPickingColor(gl_FragColor);
}`;


Insert cell
getModel = {
const {Model, Geometry} = luma;

// required for tooltip
const {picking} = deck
return gl => {
// Four corners of the quad
const positions = new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]);
const geometry = new Geometry({
drawMode: gl.TRIANGLE_FAN,
vertexCount: 4,
attributes: {
positions: {size: 2, value: positions}
}
});
return new Model(gl, {
vs: vertexShader, fs:
fragmentShader,
geometry,
isInstanced: true,
// required for tooltip
modules: [picking]
});
}
}
Insert cell
Insert cell
// deck = require.alias({
// // optional dependencies
// h3: {}
// })('deck.gl@latest/dist.min.js')

deck = require.alias({
// optional dependencies
h3: {}
})('deck.gl@v8-latest/dist.min.js')
Insert cell
luma = deck && window.luma
Insert cell
d3 = require("d3@5")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more