Last active
July 10, 2018 15:36
-
-
Save ramiroaznar/8c055a821e3446d8a4f11656402de705 to your computer and use it in GitHub Desktop.
Dynamic legends with CARTO.js v4
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> | |
<title>Dynamic legends with CARTO.js 4</title> | |
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> | |
<link rel="shortcut icon" href="https://cartodb.com/assets/favicon.ico" /> | |
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet"> | |
<!-- leaflet, jquery & axios--> | |
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script> | |
<link href="https://unpkg.com/[email protected]/dist/leaflet.css" rel="stylesheet"> | |
<script src="https://unpkg.com/axios/dist/axios.min.js"></script> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> | |
<!-- selec2 --> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" /> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script> | |
<!-- carto.js --> | |
<script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/v4.0.0-beta.4/carto.min.js"></script> | |
<link href="style.css" rel="stylesheet"></style> | |
</head> | |
<body> | |
<!-- map div --> | |
<div id="map"></div> | |
<!-- dropdown field selector --> | |
<div id="wraper-field-selector"> | |
<select class="js-field-selector"> | |
<option disabled="disabled" selected>Select field</option> | |
</select> | |
</div> | |
<!-- legend --> | |
<div id="legend"> | |
<h1>Dynamic Legends</h1> | |
<div id="legend-content"> | |
</div> | |
</div> | |
<script type="text/cartocss" id="style"> | |
#layer { | |
marker-width: 7; | |
marker-fill: #EE4D5A; | |
marker-fill-opacity: 0.9; | |
marker-line-color: #FFFFFF; | |
marker-line-width: 1; | |
marker-line-opacity: 1; | |
marker-type: ellipse; | |
marker-allow-overlap: true; | |
} | |
</script> | |
<script type="text/sql" id="query"> | |
SELECT | |
* | |
FROM | |
populated_places | |
WHERE | |
pop_max > 0 | |
ORDER BY | |
pop_max DESC | |
</script> | |
<script typ="text/javascript" src="main.js"></script> | |
</body> | |
</html> |
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
function main() { | |
/* Add CARTO map */ | |
// get styles, query, legend & selector | |
const style = $("#style").text(), query = $("#query").text(), | |
// add map variable | |
map = L.map('map', { | |
zoomControl: false, | |
center: [41, -25], | |
zoom: 3 | |
}); | |
// add Voyager Basemap | |
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', { | |
maxZoom: 18, | |
}).addTo(map); | |
// Adding Voyager Labels | |
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}.png', { | |
maxZoom: 18, | |
zIndex: 100 | |
}).addTo(map); | |
// add client | |
const client = new carto.Client({ | |
apiKey: 'default_public', | |
username: 'ramirocartodb' | |
}); | |
// define layer configuration | |
const citiesDataset = new carto.source.SQL(query), | |
citiesStyle = new carto.style.CartoCSS(style), | |
citiesLayer = new carto.layer.Layer(citiesDataset, citiesStyle); | |
// add layer | |
client.addLayer(citiesLayer); | |
client.getLeafletLayer().addTo(map); | |
/* Add field selector */ | |
const selector = $(".js-field-selector"), | |
fields = [ | |
{name: "pop_max", text: "Population", type: "numeric"}, | |
{name: "featurecla", text: "Type of city", type: "string"} | |
]; | |
fields.forEach(field => { | |
console.log(field) | |
selector.append(`<option value="${field.name}" data-type="${field.type}">${field.text}</option>`); | |
}); | |
selector.select2(); | |
/* Change style when selecting a field */ | |
selector.change(function(){ | |
// get field name & data type | |
let inputField = $( ".js-field-selector option:selected" ).val(), | |
inputType = $( ".js-field-selector option:selected" ).attr('data-type'); | |
console.log(inputField, inputType); | |
// change style | |
if (inputType === 'numeric'){ | |
citiesStyle.setContent(` | |
#layer { | |
marker-width: ramp(${inputField}, range(1.5,12), quantiles); | |
marker-fill: ramp(${inputField}, cartocolor(Sunset), quantiles); | |
marker-fill-opacity: 0.7; | |
marker-line-width: 0; | |
marker-type: ellipse; | |
marker-allow-overlap: true; | |
} | |
`); | |
} else { | |
citiesStyle.setContent(` | |
#layer { | |
marker-width: 7; | |
marker-fill: ramp(${inputField}, cartocolor(Bold), category); | |
marker-fill-opacity: 0.7; | |
marker-line-width: 0; | |
marker-type: ellipse; | |
marker-allow-overlap: true; | |
} | |
`); | |
} | |
}); | |
/* change legend when style changes */ | |
const legend = $("#legend-content"); | |
citiesLayer.on('metadataChanged', function(event){ | |
legend.empty(); | |
console.log(event); | |
const styles = event.styles; | |
// append classes to the legend | |
if (styles.length == 0){ | |
console.log("Load default legend."); | |
legend.append(`<li><div class="circle" style="background: #EE4D5A"></div> Populated Place</li>`) | |
} else if (styles.length == 1) { | |
console.log("Load category legend.") | |
const categories = styles[0].getCategories(); | |
console.log(categories); | |
for (category of categories){ | |
legend.append(`<li><div class="circle" style="background:${category.value}"></div> ${category.name}</li>`) | |
} | |
} else { | |
console.log("Load gradient legend."); | |
const styles1 = styles[0].getBuckets(), styles2 = styles[1].getBuckets(); | |
$(styles1).each(function(i, e) { | |
if (typeof(styles1[i].value) === "string"){ | |
legend.prepend(`<li><div class="circle" style="background:${styles1[i].value}; width:${styles2[i].value}px; height:${styles2[i].value}px;"></div> ${styles1[i].min} - ${styles1[i].max}</li>`); | |
} else { | |
legend.prepend(`<li><div class="circle" style="background:${styles2[i].value}; width:${styles1[i].value}px; height:${styles1[i].value}px;"></div> ${styles1[i].min} - ${styles1[i].max}</li>`) | |
} | |
}); | |
} | |
}); | |
} | |
window.onload = main; |
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
* { | |
box-sizing: border-box; | |
} | |
body, *{ margin: 0; padding: 0; } | |
#map { | |
position: absolute; | |
height: 100%; | |
width: 100%; | |
z-index: 0; | |
} | |
#wraper-field-selector { | |
position: absolute; | |
top: 20px; | |
right: 20px; | |
z-index: 2; | |
} | |
.js-field-selector { | |
width: 160px; | |
} | |
#legend { | |
position: absolute; | |
bottom: 12px; | |
left: 12px; | |
height: auto; | |
width: auto; | |
padding: 20px 24px; | |
background: white; | |
box-shadow: 0 0 16px rgba(0, 0, 0, 0.12); | |
border-radius: 4px; | |
opacity: 0.7; | |
z-index: 1; | |
display: block; | |
list-style-type: none; | |
} | |
#legend h1 { | |
font: 800 12px/16px 'Montserrat'; | |
text-transform: uppercase; | |
color: #2D3C43; | |
margin-bottom: 12px; | |
} | |
#legend-content{ | |
font: 800 12px/16px 'Open Sans'; | |
margin-bottom: 6px; | |
} | |
#legend-content > li { | |
margin-bottom: 6px; | |
display: flex; | |
align-items: center; | |
text-transform: uppercase; | |
} | |
#legend-content > li:last-child { | |
margin-bottom: 0; | |
} | |
.circle { | |
width: 8px; | |
height: 8px; | |
border-radius: 50%; | |
margin-right: 8px; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment