Created
July 4, 2020 13:01
-
-
Save rowanwins/244620182f586547a4b90c7e3c23ef68 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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