Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save rowanwins/244620182f586547a4b90c7e3c23ef68 to your computer and use it in GitHub Desktop.
Save rowanwins/244620182f586547a4b90c7e3c23ef68 to your computer and use it in GitHub Desktop.
import React, {createRef, Component} from 'react';
import {render} from 'react-dom';
import {StaticMap} from 'react-map-gl';
import DeckGL, {TileLayer, BitmapLayer} from 'deck.gl';
import {interpolateViridis, interpolateInferno} from 'd3-scale-chromatic'
import Pbf from 'pbf'
const MAPBOX_TOKEN = '...'
let INITIAL_VIEW_STATE = {
latitude: -25.734968,
longitude: 134.489563,
zoom: 4,
bearing: 0,
pitch: 30
};
function makeRequest(method, url) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response);
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
function convertRange (value, r1, r2) {
return (value - r1[0]) * (r2[1] - r2[0]) / (r1[1] - r1[0]) + r2[0]
}
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : null
}
function computeImg (data, imgInterpolate) {
const arrLength = 256 * 256 * 4
for (let i = 0; i < arrLength / 4; i++) {
if (data._rawData.values[i] !== 999) {
const newVal = convertRange(data._rawData.values[i], [0, 96], [0, 1]);
const hexVal = imgInterpolate(newVal)
const rgba = hexToRgb(hexVal);
data.data[i * 4] = rgba[0];
data.data[(i * 4) + 1] = rgba[1];
data.data[(i * 4) + 2] = rgba[2];
data.data[(i * 4) + 3] = 255;
}
}
}
class Root extends Component {
constructor(props) {
super(props);
this.deckRef = createRef()
this.state = {
colorScheme: interpolateViridis,
schemeName: 'viridis'
};
}
_onClick(info) {
this.setState(state => ({
schemeName: 'inferno',
colorScheme: interpolateInferno
}))
this.deckRef.current.props.layers[0].state.tileset._cache = new Map()
}
render() {
console.log('RENDER CALLED')
const layers = [new TileLayer({
data: 'http://localhost:3000/{z}/{x}/{y}.pbf',
minZoom: 0,
maxZoom: 19,
schemeName: this.state.schemeName,
colorScheme: this.state.colorScheme,
tileSize: 256,
pickable: true,
onClick: this._onClick.bind(this),
getTileData: async function (tile) {
const data = await makeRequest("GET", tile.url);
const out = new ImageData(256, 256);
if (data) {
var pbfData = new Pbf(data);
out._rawData = ImgPbf.read(pbfData);
}
return out
},
renderSubLayers: props => {
console.log('RENDER SUBLAYERS CALLED', props.schemeName)
const {
bbox: {west, south, east, north}
} = props.tile;
if (props.tile.data) {
computeImg(props.tile.data, props.colorScheme)
}
return new BitmapLayer(props, {
data: null,
image: props.tile.data,
bounds: [west, south, east, north]
});
}
})];
return (
<DeckGL initialViewState={INITIAL_VIEW_STATE} controller={true} layers={layers} ref={this.deckRef}>
<StaticMap mapboxApiAccessToken={MAPBOX_TOKEN} mapStyle="mapbox://styles/mapbox/light-v9" />
</DeckGL>
);
}
}
var ImgPbf = {};
ImgPbf.read = function (pbf, end) {
return pbf.readFields(ImgPbf._readField, {values: []}, end);
};
ImgPbf._readField = function (tag, obj, pbf) {
if (tag === 3) pbf.readPackedVarint(obj.values, true);
};
ImgPbf.write = function (obj, pbf) {
if (obj.values) pbf.writePackedVarint(3, obj.values);
};
/* global document */
render(<Root />, document.body.appendChild(document.createElement('div')));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment