Skip to content

Instantly share code, notes, and snippets.

@ryanbaumann
Last active July 11, 2022 21:24
Show Gist options
  • Save ryanbaumann/733ba99c5ca1d9d15259081b395e4b00 to your computer and use it in GitHub Desktop.
Save ryanbaumann/733ba99c5ca1d9d15259081b395e4b00 to your computer and use it in GitHub Desktop.
GL JS Feature States with Data Joins
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Display a map</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css' rel='stylesheet' />
<script src='https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.0.3/chroma.min.js'></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id='map'>
</div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoicnNiYXVtYW5uIiwiYSI6ImNqNmhkZnhkZDA4M3Yyd3AwZDR4cmdhcDIifQ.TGKKAC6pPP0L-uMDJ5xFAA';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10?optimize=true',
center: [-99.9, 41.5],
zoom: 3
});
var maxValue = 0;
var newdata = new Map();
var breaks = [];
var scale = [];
var getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status === 200) {
callback(null, xhr.response);
} else {
callback(status, xhr.response);
}
};
xhr.send();
};
var domain = [];
var processData = function(err, data) {
if (err !== null) {
console.log('error fetching file')
} else {
data.forEach(function(row) {
if (!row["Zip Code ZCTA"]) {
return
}
// Normalized population density
let area = row['area'] > 0 ? row['area'] : 1;
maxValue = row["2010 Census Population"] <= maxValue ? maxValue : row["2010 Census Population"];
domain.push(row["2010 Census Population"])
newdata[row["Zip Code ZCTA"]] = {
population: row["2010 Census Population"],
area: row['area'],
ratio: row["2010 Census Population"] / (area / 5280)
}
});
breaks = chroma.limits(domain, 'q', 5);
scale = chroma.scale('RdPu').colors(6);
if (map.loaded()) {
initLayers();
} else {
map.on('load', initLayers)
}
}
}
getJSON('https://dl.dropbox.com/s/0vtzw9aw089obxi/population.json', processData);
function initLayers() {
map.addSource("postcodes", {
type: "vector",
url: "mapbox://mapbox.pbi-us-postcodes-v1",
});
map.addLayer({
"id": "postcodes",
"type": "fill",
"source": "postcodes",
"source-layer": "pbi-us-postcodes",
"paint": {
"fill-color": 'rgba(0,0,0,0)',
"fill-opacity": ["case", ['==', ["feature-state", 'hover'], 1], 1, 0.8]
}
}, 'waterway-label');
map.addLayer({
"id": "postcodes-line",
"type": "line",
"source": "postcodes",
"source-layer": "pbi-us-postcodes",
"paint": {
"line-color": ['case', ['==', ["feature-state", 'hover'], 1], 'black', 'rgba(0,0,0,0)'],
"line-width": 2
}
}, 'waterway-label');
function createColorExpression(stops, colors, value) {
var expression = ['case', ['==', ["feature-state", 'hover'], 1], 'rgb(122,1,119)', ['interpolate', ['linear'],
['to-number', value]
]]
for (var i = 0; i < stops.length; i++) {
expression[3].push(stops[i])
expression[3].push(colors[i])
}
return expression
}
function setPostcodes() {
for (var key in newdata) {
map.setFeatureState({
source: 'postcodes',
sourceLayer: 'pbi-us-postcodes',
id: key
}, {
'colorValue': newdata[key]['population'] != undefined ? newdata[key]['population'] : 0
})
}
map.setPaintProperty('postcodes', 'fill-color', createColorExpression(breaks, scale, ['feature-state', 'colorValue']))
}
var hoverId = 0;
var popup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false
});
var onLoad = function(e) {
if (map.isSourceLoaded('postcodes')) {
setPostcodes();
map.off('sourcedata', onLoad);
}
};
if (map.isSourceLoaded('postcodes')) {
setPostcodes();
} else {
map.on('sourcedata', onLoad);
}
var onMouseMove = function(e) {
var features = map.queryRenderedFeatures(e.point, {
layers: ['postcodes']
});
if (!features.length) {
map.getCanvas().style.cursor = '';
map.setFeatureState({
source: 'postcodes',
sourceLayer: 'pbi-us-postcodes',
id: hoverId
}, { 'hover': 0 })
hoverId = 0;
return
}
map.getCanvas().style.cursor = 'pointer';
let newHoverId = features[0].id;
if (newHoverId != hoverId) {
map.setFeatureState({
source: 'postcodes',
sourceLayer: 'pbi-us-postcodes',
id: hoverId
}, { 'hover': 0 })
hoverId = newHoverId
}
map.setFeatureState({
source: 'postcodes',
sourceLayer: 'pbi-us-postcodes',
id: hoverId
}, { 'hover': 1 })
};
map.on('mousemove', onMouseMove);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment