* Load svg icon appears while data is loading
* Uncompressed geojson file is 29 MB on dropbox
* Total time to load depends on client internet speed & client GPU
* Geojson source is split into two parts to optimize load and render time
-
-
Save iisstizzy/9c2efbb2f3099c26d07405b0bc986ea6 to your computer and use it in GitHub Desktop.
Example of loading large geojson into Mapbox GL JS
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></title> | |
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> | |
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.js'></script> | |
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.7.0/mapbox-gl.css' rel='stylesheet' /> | |
<link href='https://www.mapbox.com/base/latest/base.css' rel='stylesheet' /> | |
<style> | |
body { | |
margin: 0; | |
padding: 0; | |
} | |
#map { | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
width: 100%; | |
} | |
.map-overlay { | |
position: absolute; | |
width: 180px; | |
top: 0; | |
left: 10px; | |
padding: 10px; | |
margin-left: 5px; | |
margin-top: 2px; | |
margin-bottom: 2px; | |
margin-right: 5px; | |
z-index: 1; | |
} | |
.map-overlay .map-overlay-inner { | |
background: rgba(0, 0, 0, .8); | |
color: #fff; | |
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10); | |
border-radius: 3px; | |
padding: 10px; | |
margin-bottom: 10px; | |
z-index: 1; | |
} | |
.map-overlay-inner fieldset { | |
border: none; | |
padding: 0; | |
margin: 0 0 10px; | |
z-index: 1; | |
} | |
/* Dark attribution */ | |
.mapboxgl-ctrl.mapboxgl-ctrl-attrib { | |
background: rgba(0, 0, 0, .8); | |
} | |
.mapboxgl-ctrl.mapboxgl-ctrl-attrib a { | |
color: #fff; | |
} | |
/* Dark popup */ | |
.mapboxgl-popup-content { | |
background-color: #202020; | |
color: #fff; | |
margin-left: 5px; | |
margin-top: 2px; | |
margin-bottom: 2px; | |
margin-right: 5px; | |
z-index: 1000; | |
} | |
.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip, | |
.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip, | |
.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip { | |
border-top-color: #202020; | |
} | |
.mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip, | |
.mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip, | |
.mapboxgl-popup-anchor-top .mapboxgl-popup-tip { | |
border-bottom-color: #202020; | |
} | |
.mapboxgl-popup-anchor-right .mapboxgl-popup-tip { | |
border-left-color: #202020; | |
} | |
.mapboxgl-popup-anchor-left .mapboxgl-popup-tip { | |
border-right-color: #202020; | |
} | |
#popup-menu ul, | |
#menu li { | |
margin: 0; | |
padding: 0; | |
z-index: 100; | |
} | |
.mapboxgl-ctrl-group { | |
-webkit-filter: invert(100%); | |
} | |
.loader { | |
margin: -10px 0 0 -250px; | |
height: 100px; | |
width: 20%; | |
position: fixed; | |
text-align: center; | |
padding: 1em; | |
top: 50%; | |
left: 50%; | |
margin: 0 auto 1em; | |
z-index: 9999; | |
} | |
/* | |
Set the color of the icon | |
*/ | |
svg path, | |
svg rect { | |
fill: #FF6700; | |
} | |
</style> | |
</head> | |
<body> | |
<div id='map'></div> | |
<div class='map-overlay top'> | |
<div class='map-overlay-inner'> | |
<fieldset> | |
<label><b>Select property</b></label> | |
<select id='prop' name='prop'> | |
<option value='CYC_INJ'>Cyclist Injuries</option> | |
<option value='CYC_KIL'>Cyclist Fatalities</option> | |
<option value='PED_INJ'>Pedestrian Injuries</option> | |
<option value='PED_KIL'>Pedestrian Fatalities</option> | |
</select> | |
</fieldset> | |
<b><a href="https://data.cityofnewyork.us/Public-Safety/NYPD-Motor-Vehicle-Collisions/h9gi-nx95" target="_blank">NYC Open Data</a></b> | |
</div> | |
</div> | |
<div class="loader loader--style1" title="0" id="loader"> | |
<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="40px" height="40px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve"> | |
<path opacity="0.2" fill="#000" d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946 | |
s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634 | |
c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z" /> | |
<path fill="#000" d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0 | |
C22.32,8.481,24.301,9.057,26.013,10.047z"> | |
<animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 20 20" to="360 20 20" dur="0.5s" repeatCount="indefinite" /> | |
</path> | |
</svg> | |
</div> | |
<script> | |
mapboxgl.accessToken = 'pk.eyJ1IjoicnNiYXVtYW5uIiwiYSI6ImNqNmhkZnhkZDA4M3Yyd3AwZDR4cmdhcDIifQ.TGKKAC6pPP0L-uMDJ5xFAA'; | |
var bounds = [ | |
[-75.04728500751165, 39.68392799015035], | |
[-72.91058699000139, 41.87764500765852] | |
]; | |
var map = new mapboxgl.Map({ | |
container: 'map', | |
style: 'mapbox://styles/mapbox/dark-v9', | |
center: [-74.0059, 40.7128], | |
zoom: 10, | |
minZoom: 9, | |
maxZoom: 18, | |
pitch: 40, | |
maxBounds: bounds | |
}); | |
function init() { | |
map.addSource('veh-incidents-1', { | |
type: 'geojson', | |
data: 'https://dl.dropbox.com/s/z4hajzr32e59kv4/nyc_pedcyc_collisions_1.geojson?dl=0', | |
buffer: 0, | |
maxzoom: 12 | |
}); | |
map.addSource('veh-incidents-2', { | |
type: 'geojson', | |
data: 'https://dl.dropbox.com/s/prxhl4whif6tstt/nyc_pedcyc_collisions_2.geojson?dl=0', | |
buffer: 0, | |
maxzoom: 12 | |
}); | |
if (window.location.search.indexOf('embed') !== -1) map.scrollZoom.disable(); | |
map.addLayer({ | |
'id': 'veh-incd-1', | |
'type': 'circle', | |
'source': 'veh-incidents-1', | |
'paint': { | |
'circle-color': { | |
property: 'CYC_INJ', | |
type: 'interval', | |
stops: [ | |
[1, 'orange'], | |
[2, 'red'] | |
] | |
}, | |
'circle-radius': { | |
property: 'CYC_INJ', | |
base: 3, | |
type: 'interval', | |
stops: [ | |
[1, 3], | |
[2, 8], | |
[3, 12] | |
] | |
}, | |
'circle-opacity': 0.8, | |
'circle-blur': 0.5 | |
}, | |
'filter': ['>=', 'CYC_INJ', 1] | |
}, 'waterway-label'); | |
map.addLayer({ | |
'id': 'veh-incd-2', | |
'type': 'circle', | |
'source': 'veh-incidents-2', | |
'paint': { | |
'circle-color': { | |
property: 'CYC_INJ', | |
type: 'interval', | |
stops: [ | |
[1, 'orange'], | |
[2, 'red'] | |
] | |
}, | |
'circle-radius': { | |
property: 'CYC_INJ', | |
base: 3, | |
type: 'interval', | |
stops: [ | |
[1, 3], | |
[2, 8], | |
[3, 12] | |
] | |
}, | |
'circle-opacity': 0.8, | |
'circle-blur': 0.5 | |
}, | |
'filter': ['>=', 'CYC_INJ', 1] | |
}, 'waterway-label'); | |
map.addLayer({ | |
'id': 'veh-incd-base-1', | |
'type': 'circle', | |
'source': 'veh-incidents-1', | |
'paint': { | |
'circle-color': 'yellow', | |
'circle-radius': 3, | |
'circle-opacity': 0.3, | |
'circle-blur': 1 | |
}, | |
'filter': ['<', 'CYC_INJ', 1] | |
}, 'waterway-label'); | |
map.addLayer({ | |
'id': 'veh-incd-base-2', | |
'type': 'circle', | |
'source': 'veh-incidents-2', | |
'paint': { | |
'circle-color': 'yellow', | |
'circle-radius': 3, | |
'circle-opacity': 0.3, | |
'circle-blur': 1 | |
}, | |
'filter': ['<', 'CYC_INJ', 1] | |
}, 'waterway-label'); | |
}; | |
map.once('style.load', function(e) { | |
init(); | |
map.addControl(new mapboxgl.NavigationControl()); | |
map.on('click', function(e) { | |
var features = map.queryRenderedFeatures(e.point, { | |
layers: ['veh-incd-1', 'veh-incd-2'] | |
}); | |
if (!features.length) { | |
return; | |
} | |
var feature = features[0]; | |
var popup = new mapboxgl.Popup() | |
.setLngLat(map.unproject(e.point)) | |
.setHTML('<h3>Collision Detail</h3>' + | |
'<ul>' + | |
'<li>Year: <b>' + feature.properties.YEAR + '</b></li>' + | |
'<li>Pedestrian Injuries: <b>' + feature.properties.PED_INJ + '</b></li>' + | |
'<li>Pedestrian Fatalities: <b>' + feature.properties.PED_KIL + '</b></li>' + | |
'<li>Cyclist Injuries: <b>' + feature.properties.CYC_INJ + '</b></li>' + | |
'<li>Cyclist Fatalities: <b>' + feature.properties.CYC_KIL + '</b></li>' + | |
'</ul>') | |
.addTo(map); | |
}); | |
//Hide loading bar once tiles from geojson are loaded | |
map.on('data', function(e) { | |
if (e.dataType === 'source' && e.sourceId === 'veh-incidents-1') { | |
document.getElementById("loader").style.visibility = "hidden"; | |
} | |
}) | |
// Use the same approach as above to indicate that the symbols are clickable | |
// by changing the cursor style to 'pointer'. | |
map.on('mousemove', function(e) { | |
var features = map.queryRenderedFeatures(e.point, { | |
layers: ['veh-incd-1', 'veh-incd-2'] | |
}); | |
map.getCanvas().style.cursor = (features.length) ? 'pointer' : ''; | |
}); | |
var prop = document.getElementById('prop'); | |
prop.addEventListener('change', function() { | |
map.setPaintProperty('veh-incd-1', 'circle-color', { | |
property: prop.value, | |
type: 'interval', | |
stops: [ | |
[1, 'orange'], | |
[2, 'red'] | |
] | |
}); | |
map.setPaintProperty('veh-incd-2', 'circle-color', { | |
property: prop.value, | |
type: 'interval', | |
stops: [ | |
[1, 'orange'], | |
[2, 'red'] | |
] | |
}); | |
map.setPaintProperty('veh-incd-1', 'circle-radius', { | |
property: prop.value, | |
base: 3, | |
type: 'interval', | |
stops: [ | |
[1, 3], | |
[2, 6], | |
[3, 9] | |
] | |
}); | |
map.setPaintProperty('veh-incd-2', 'circle-radius', { | |
property: prop.value, | |
base: 3, | |
type: 'interval', | |
stops: [ | |
[1, 3], | |
[2, 6], | |
[3, 9] | |
] | |
}); | |
map.setFilter('veh-incd-1', ['>=', prop.value, 1]) | |
map.setFilter('veh-incd-2', ['>=', prop.value, 1]) | |
}); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment