-
-
Save ryanbaumann/733ba99c5ca1d9d15259081b395e4b00 to your computer and use it in GitHub Desktop.
GL JS Feature States with Data Joins
This file contains 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
<!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