Skip to content

Instantly share code, notes, and snippets.

@padawannn
Created March 15, 2018 08:42
Show Gist options
  • Save padawannn/357d73b178a4d532c4cc5b9e3daf8dca to your computer and use it in GitHub Desktop.
Save padawannn/357d73b178a4d532c4cc5b9e3daf8dca to your computer and use it in GitHub Desktop.
Carto-1M-points
<!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