Published
Edited
Jul 8, 2022
2 forks
10 stars
Insert cell
Insert cell
Insert cell
Insert cell
deckgl = {
const props = {
container,
views: new deck.OrthographicView(),
initialViewState: {
target: [300, 0, 0],
zoom: 0,
minZoom: 0
},
controller: true,
layers,
getTooltip: ({layer}) => layer && layer.id.split('#')[0]
};
// Avoid creating multiple instances
const prevDeckInstance = this;
if (prevDeckInstance) {
prevDeckInstance.setProps(props);
return prevDeckInstance;
}
return new deck.DeckGL(props);
}
Insert cell
layers = [
bitmapLayer,
contrastLayer,
colorRemapLayer,
hueShiftLayer,
vignetteLayer
]
Insert cell
Insert cell
bitmapLayer = {
return new deck.BitmapLayer({
id: `Original BitmapLayer#${Math.random()}`,
pickable: true,
image: IMAGE_URL,
bounds: [0, 100, 200, -100]
})
}
Insert cell
contrastLayer = {
class ContrastBitmapLayer extends deck.BitmapLayer {
getShaders() {
return {
...super.getShaders(),
inject: {
'fs:#decl': `
uniform float brightness;
uniform float contrast;`,
'fs:DECKGL_FILTER_COLOR': `
float grayscale = (color.r + color.g + color.b) / 3.0 + brightness;
float newGrayscale = (grayscale - 0.5) * contrast + 0.5;
color.rgb *= grayscale == 0.0 ? newGrayscale : newGrayscale / grayscale;`
}
}
}
draw(opts) {
const {brightness, contrast} = this.props;
opts.uniforms.brightness = brightness;
opts.uniforms.contrast = contrast;
super.draw(opts);
}
}
return new ContrastBitmapLayer({
id: `BitmapLayer with contrast#${Math.random()}`,
pickable: true,
image: IMAGE_URL,
bounds: [220, 100, 420, -100],
brightness: -0.3,
contrast: 1.6
});
}
Insert cell
colorRemapLayer = {
class ColorRemapBitmapLayer extends deck.BitmapLayer {
getShaders() {
return {
...super.getShaders(),
inject: {
'fs:#decl': `
uniform vec4 fromColor;
uniform vec4 toColor;`,
'fs:DECKGL_FILTER_COLOR': `
float grayscale = (color.r + color.g + color.b) / 3.0;
color = mix(fromColor, toColor, grayscale);`
}
}
}
draw(opts) {
const {colorRange} = this.props;
opts.uniforms.fromColor = colorRange[0].map(x => x / 255);
opts.uniforms.toColor = colorRange[1].map(x => x / 255);
super.draw(opts);
}
}
return new ColorRemapBitmapLayer({
id: `BitmapLayer with color remapping#${Math.random()}`,
pickable: true,
image: IMAGE_URL,
bounds: [440, 100, 640, -100],
colorRange: [[235, 0, 0, 255], [0, 255, 125, 255]]
});
}
Insert cell
hueShiftLayer = {
class HueShiftBitmapLayer extends deck.BitmapLayer {
getShaders() {
return {
...super.getShaders(),
inject: {
'fs:#decl': `
uniform mat3 hueTransform;`,
'fs:DECKGL_FILTER_COLOR': `
color.rgb = hueTransform * color.rgb;`
}
}
}
draw(opts) {
const {hueShift} = this.props;
// https://stackoverflow.com/questions/8507885/shift-hue-of-an-rgb-color
const U = Math.cos(hueShift * Math.PI / 180);
const W = Math.sin(hueShift * Math.PI / 180);

opts.uniforms.hueTransform = [
.299+.701*U+.168*W,
.299-.299*U-.328*W,
.299-.3*U+1.25*W,
.587-.587*U+.330*W,
.587+.413*U+.035*W,
.587-.588*U-1.05*W,
.114-.114*U-.497*W,
.114-.114*U+.292*W,
.114+.886*U-.203*W
];
super.draw(opts);
}
}
return new HueShiftBitmapLayer({
id: `BitmapLayer with hue shift#${Math.random()}`,
pickable: true,
image: IMAGE_URL,
bounds: [660, 100, 860, -100],
hueShift: -120
});
}
Insert cell
vignetteLayer = {
class VignetteBitmapLayer extends deck.BitmapLayer {
getShaders() {
return {
...super.getShaders(),
inject: {
'fs:#decl': `
uniform float vignette;`,
'fs:DECKGL_FILTER_COLOR': `
float distToCenter = distance(geometry.uv, vec2(0.5));
color.rgb *= smoothstep(0.7, 0.3, distToCenter) * vignette + 1.0 - vignette;`
}
}
}
draw(opts) {
const {vignette} = this.props;
opts.uniforms.vignette = vignette;
super.draw(opts);
}
}
return new VignetteBitmapLayer({
id: `BitmapLayer with vignette#${Math.random()}`,
pickable: true,
image: IMAGE_URL,
bounds: [880, 100, 1080, -100],
vignette: 1.0
});
}
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more