Created
March 15, 2018 08:42
-
-
Save padawannn/357d73b178a4d532c4cc5b9e3daf8dca to your computer and use it in GitHub Desktop.
Carto-1M-points
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset='utf-8' /> | |
<title>MapboxGL CARTO Building</title> | |
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> | |
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.js'></script> | |
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css' rel='stylesheet' /> | |
<style> | |
body { margin:0; padding:0; } | |
#map { position:absolute; top:0; bottom:0; width:100%; } | |
#rangeWrapper { | |
display: none; | |
position: absolute; | |
right: 0; | |
bottom: 26px; | |
padding: 12px; | |
z-index: 1; | |
background-color: #fff; | |
} | |
#rangeWrapper >div { | |
display: flex; | |
justify-content: space-between; | |
} | |
#filterWrapper{ | |
position: absolute; | |
top: 0; | |
left: 0; | |
background-color: #fff; | |
z-index: 1; | |
padding: 12px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id='map'></div> | |
<div id="rangeWrapper"> | |
<h3>Agregation resolution</h3> | |
<div> | |
<input id="range" type="range" min="1" max="16" value="1" step="1" onchange="reloadAggregatedLayer()"> | |
<label id="rangeLabel" for="range"></label> | |
</div> | |
</div> | |
<div id="filterWrapper"> | |
<input id="shopping" type="checkbox" checked value="3" onchange="loadLayers()"> | |
<label style="border-bottom: 1px solid red;" for="shopping">Shopping</label> | |
<input id="amusement_hobbies" type="checkbox" checked value="2" onchange="loadLayers()"> | |
<label style="border-bottom: 1px solid brown;" for="amusement_hobbies">Amusement and hobbies</label> | |
<input id="health_security" type="checkbox" checked value="6" onchange="loadLayers()"> | |
<label style="border-bottom: 1px solid blue;" for="health_security">Health and security</label> | |
<input id="education" type="checkbox" checked value="7" onchange="loadLayers()"> | |
<label style="border-bottom: 1px solid green;" for="education">Education</label> | |
<input id="transportation" type="checkbox" checked value="5" onchange="loadLayers()"> | |
<label style="border-bottom: 1px solid yellow;" for="transportation">Transportation</label> | |
<input id="tourism_culture" type="checkbox" checked value="1" onchange="loadLayers()"> | |
<label style="border-bottom: 1px solid pink;" for="tourism_culture">Tourism and culture</label> | |
<input id="food_drinks" type="checkbox" checked value="4" onchange="loadLayers()"> | |
<label style="border-bottom: 1px solid purple;" for="food_drinks">Food and drinks</label> | |
<input id="other_services" type="checkbox" checked value="8" onchange="loadLayers()"> | |
<label style="border-bottom: 1px solid cyan;"for="other_services">Other services</label> | |
</div> | |
<script> | |
const map = new mapboxgl.Map({ | |
container: 'map', | |
center: [-3.8196205, 40.4378698], | |
style: 'http://basemaps.cartocdn.com/gl/voyager-gl-style/style.json', | |
zoom: 5 | |
}), | |
popup = new mapboxgl.Popup(); | |
; | |
let filter = ''; | |
map.on('load', function(){ | |
loadLayers(); | |
}); | |
function loadLayers(){ | |
let checkboxes = document.querySelectorAll('input[type=checkbox]:checked'); | |
filter = ''; | |
for (const c of checkboxes){ | |
filter += `group_id=${c.value} OR `; | |
} | |
filter = checkboxes.length === 0 ? 'FALSE' : filter.slice(0, filter.length-3); | |
reloadAggregatedLayer(); | |
reloadNoAggregatedLayer(); | |
} | |
async function reloadAggregatedLayer() { | |
const value = parseInt(document.getElementById("range").value); | |
document.getElementById("rangeLabel").textContent = value; | |
const mapConfig = { | |
buffersize: { mvt: 0 }, | |
layers: [ | |
{ | |
id: 'aggregated', | |
type: 'mapnik', | |
options: { | |
sql: `SELECT * FROM pois WHERE ${filter}`, | |
aggregation: { | |
threshold: 1, // Force aggregation | |
resolution: value, | |
placement: 'centroid', | |
columns: { | |
total: { | |
aggregate_function: 'sum', | |
aggregated_column: 'group_id' | |
} | |
} | |
} | |
} | |
} | |
] | |
}, | |
tilejson = await getTiles(mapConfig); | |
; | |
if (map.getLayer('pois_aggregated')) { | |
map.removeLayer('pois_aggregated'); | |
map.removeSource('pois_aggregated_source'); | |
// map.off('click', 'pois_aggregated', aggregatedPoiClicked); | |
} | |
map.addSource('pois_aggregated_source', { type: 'vector', tiles: tilejson }); | |
map.addLayer({ | |
id: 'pois_aggregated', | |
type: 'circle', | |
maxzoom: 14, | |
source: 'pois_aggregated_source', | |
'source-layer': 'aggregated', | |
paint: { | |
'circle-color': '#b13f64', | |
'circle-stroke-width': 1, | |
'circle-stroke-color': '#fff', | |
'circle-radius': 2 | |
} | |
}); | |
// map.on('click', 'pois_aggregated', aggregatedPoiClicked); | |
} | |
async function reloadNoAggregatedLayer() { | |
const mapConfig = { | |
buffersize: { mvt: 0 }, | |
layers: [ | |
{ | |
id: 'no_aggregated', | |
type: 'mapnik', | |
options: { | |
sql: `SELECT * FROM pois WHERE ${filter}`, | |
aggregation: false | |
} | |
} | |
] | |
}, | |
tilejson = await getTiles(mapConfig); | |
; | |
if (map.getLayer('pois')) { | |
map.removeLayer('pois'); | |
map.removeSource('pois_source'); | |
map.off('mouseenter', 'pois', poiClicked); | |
} | |
map.addSource('pois_source', { type: 'vector', tiles: tilejson }); | |
map.addLayer({ | |
id: 'pois', | |
type: 'circle', | |
minzoom: 14, | |
source: 'pois_source', | |
'source-layer': 'no_aggregated', | |
paint: { | |
// 'circle-color': '#b13f64', | |
'circle-color': [ | |
'match', | |
['get', '_group'], | |
'Amusement and hobbies', 'brown', | |
'Shopping', 'red', | |
'Health and security', 'blue', | |
'Education', 'green', | |
'Transportation', 'yellow', | |
'Tourism and culture', 'pink', | |
'Food and drinks', 'purple', | |
'Other services', 'cyan', | |
'#ccc' | |
], | |
'circle-stroke-width': 1, | |
'circle-stroke-color': '#fff' | |
} | |
}); | |
map.on('mouseenter', 'pois', poiClicked); | |
} | |
async function getTiles(mapConfig) { | |
const response = await fetch('https://paulajulia.carto.com/api/v1/map', { | |
method: 'POST', | |
headers: { | |
'Accept': 'application/json', | |
'Content-Type': 'application/json' | |
}, | |
body: JSON.stringify(mapConfig) | |
}), | |
layergroup = await response.json(); | |
return layergroup.metadata.tilejson.vector.tiles; | |
} | |
function aggregatedPoiClicked(e) { | |
let total = 0; | |
for (const f of e.features) { | |
total += f.properties.total; | |
} | |
setPopup(e.lngLat, `${total} Pois`); | |
} | |
function poiClicked(e) { | |
const content = ` | |
Name: <strong>${e.features[0].properties.name}</strong> <br> | |
Group: <strong>${e.features[0].properties._group}</strong> <br> | |
Category: <strong>${e.features[0].properties._category}</strong> <br> | |
Subcategory: <strong>${e.features[0].properties._subcategory}</strong> | |
`; | |
setPopup(e.lngLat, content); | |
} | |
function setPopup(lngLat, content) { | |
popup.remove(); | |
popup.addTo(map) | |
popup.setLngLat(lngLat); | |
popup.setHTML(content); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment