Public
Edited
Jun 3
1 fork
Insert cell
Insert cell
container = html `<div style="height:300px"></div>`
Insert cell
html`
${viewof dropdown_cell}<br>
${viewof dropdown_gene}<br>
${viewof dropdown_img}<br>`
Insert cell
// obs_state.dropdown_cell.set('blue')
Insert cell
Insert cell
// update deck when newLayer is changed (to anything)
{
obs_state.newLayer.subscribe(() => {
const newScatterplotLayer = scatterplotLayer.clone({
id: 'cells-' + obs_state.dropdown_cell.get()
})

deckgl.setProps({
layers: [newScatterplotLayer],
})
})
}
Insert cell
scatterplotLayer = {
return new deck.ScatterplotLayer({
id: 'cells-all',
data: [
{position: [-122.402, 37.79], color: [255, 0, 0], radius: 100, name: 'red'},
{position: [-122.399, 37.79], color: [0, 0, 255], radius: 100, name: 'blue'},
{position: [-122.396, 37.79], color: [0, 0, 0], radius: 100, name: 'black'},
],
getPosition: d => d.position,
getColor: d => {
var inst_color
if (obs_state.dropdown_cell.get() === 'all'){
inst_color = d.color
} else {
if (obs_state.dropdown_cell.get() === d.name)
inst_color = d.color
else {
inst_color = [0, 0, 0, 50]
}
}
return inst_color
},
getRadius: d => d.radius,
opacity: 0.3,
pickable: true,
onClick: d => {
if (obs_state.dropdown_cell.get() !== d.object.name){
obs_state.dropdown_cell.set(d.object.name)
} else {
obs_state.dropdown_cell.set(obs_state.dropdown_cell.getDefault())
}
// say that a new layer needs to be made
obs_state.newLayer.set([])
}
});
}
Insert cell
deckgl.setProps({
layers: [scatterplotLayer],
controller: { doubleClickZoom: false },
initialViewState: {
longitude: -122.402,
latitude: 37.79,
zoom: 15,
pitch: 0,
bearing: 0,
},
})
Insert cell
deckgl = new deck.DeckGL({
container,
controller: true,
})
Insert cell
deck = require.alias({
// optional dependencies
h3: {}
})('deck.gl@latest/dist.min.js')
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function makeResettableDropdown({ key, label, options, resetTriggers, obs_state }) {
const dropdown = Inputs.select(options, {
label,
value: obs_state[key].getDefault()
});

// Input → Observable
dropdown.addEventListener("input", () => {
// console.log(`user input: ${key}:`, dropdown.value);
obs_state[key].set(dropdown.value);
obs_state.newLayer.set([])
// console.log("");
});

// Observable → Input
obs_state[key].subscribe(val => {
if (dropdown.value !== val) {
dropdown.value = val;
// console.log(`obs input: ${key}:`, val);
}
});

// Reset if triggered by another dropdown
const resetIfNeeded = () => {
if (obs_state.suppressReset.get()) {
// console.log(`suppressed: ${key}`);
return;
}

if (obs_state[key].get() !== obs_state[key].getDefault()) {
obs_state.suppressReset.set(true);
// console.log(`suppressReset: ${key}: on`);
obs_state[key].set(obs_state[key].getDefault());
obs_state.suppressReset.set(false);
// console.log(`suppressReset: ${key}: off`);
} else {
// console.log(`already default: ${key}`);
}
};

// set subscribe function
for (const triggerKey of resetTriggers) {
obs_state[triggerKey].subscribe(resetIfNeeded);
}

return dropdown;
}

Insert cell
Insert cell
function Observable(initialValue) {
let value = initialValue;
const subscribers = new Set();

return {
get: () => value,
getDefault: () => initialValue,
set: newValue => {
if (value !== newValue) {
value = newValue;
subscribers.forEach(fn => fn(value));
}
},
subscribe: fn => {
subscribers.add(fn);
fn(value); // Call immediately with current value
return () => subscribers.delete(fn); // Unsubscribe function
}
};
}


Insert cell
obs_state = ({
dropdown_cell: Observable("all"),
dropdown_gene: Observable("all"),
dropdown_img: Observable("all"),
suppressReset: Observable(false),
newLayer: Observable([])
})
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