Last active
June 13, 2018 07:06
-
-
Save oriolbx/541ace6b87533f9efabac440a300ef6f to your computer and use it in GitHub Desktop.
CARTO.js v4: Category widget
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" /> | |
<meta name="viewport" content="width=device-width"> | |
<!-- Include Carto.js --> | |
<script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/v4.0.2/carto.min.js"></script> | |
<!-- Include Leaflet --> | |
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"></script> | |
<link href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" rel="stylesheet"> | |
<!-- Include d3 --> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.12.0/d3.min.js"></script> | |
<style> | |
.wrapper { | |
width: 100%; | |
height: 100vh; /*view port height*/ | |
display: grid; | |
/* small screens */ | |
grid-template-areas: | |
"map" | |
"widget"; | |
grid-template-rows: 10fr 2fr; | |
} | |
@media (min-width: 700px) { | |
.wrapper{ | |
grid-template-areas: | |
"map widget"; | |
grid-template-columns: 10fr 2fr; | |
grid-template-rows: auto; | |
} | |
} | |
#map { | |
grid-area: map; | |
border-radius: 10px; | |
} | |
#box { | |
grid-area: widget; | |
border-radius: 10px; | |
padding: 5px 10px 5px 10px; | |
border: 1px solid palegreen; | |
background-color: #FFF; | |
} | |
/* set styles to the <h4> tag of the element with id= box */ | |
#box h4 { | |
text-align: center; | |
font-size: 24px; | |
font-style: italic; | |
} | |
/* set styles to the <p> tag of the element with id= box */ | |
#box p { | |
text-align: center; | |
font-size: 18px; | |
color: dodgerblue; | |
} | |
</style> | |
</head> | |
<body> | |
<div class='wrapper'> | |
<div id="map"></div> | |
<div id="box"></div> | |
</div> | |
<script> | |
const map = L.map('map').setView([30, 0], 3); | |
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', { | |
maxZoom: 18 | |
}).addTo(map); | |
// define client | |
const client = new carto.Client({ | |
apiKey: 'default_public', | |
username: 'oboix' | |
}); | |
// define source of data using a SQL query | |
const source = new carto.source.SQL(` | |
SELECT * FROM populated_places_spf | |
`); | |
// define CartoCSS code to style data on map | |
const style = new carto.style.CartoCSS(` | |
#layer[adm0name = "Spain"]{ | |
marker-fill: #fbb4ae; | |
marker-allow-overlap: true; | |
} | |
#layer[adm0name = "Portugal"]{ | |
marker-fill: #ccebc5; | |
marker-allow-overlap: true; | |
} | |
#layer[adm0name = "France"]{ | |
marker-fill: #b3cde3; | |
marker-allow-overlap: true; | |
}`); | |
// create CARTO layer from source and style variables | |
const Cartolayer = new carto.layer.Layer(source, style); | |
// add CARTO layer to the client | |
client.addLayer(Cartolayer); | |
// get tile from client and add them to the map object | |
client.getLeafletLayer().addTo(map); | |
// create formula dataview using pop_max column values | |
// SUM formula | |
const categoryDataview = new carto.dataview.Category(source, 'adm0name', { | |
limit: 10, | |
operation: carto.operation.SUM, | |
operationColumn: 'pop_max' | |
}); | |
// define variable that will store an array of values | |
let categoriesArray = []; | |
// when there is a change on the data, execute function to | |
// display result from dataview in DOM element | |
categoryDataview.on('dataChanged', function(data){ | |
categoriesArray = []; | |
// data.categories is an array of objects -> [{},{},{},...] | |
let categories = data.categories; | |
// Use D3.js library to format text with comma separator for thousands | |
let commaSeparator = d3.format(","); | |
// set values array | |
categories.forEach(function(data){ | |
categoriesArray.push(data.value) | |
}); | |
// use categoriesArray values to define the domain of the data | |
let x = d3.scaleLinear() | |
.domain([0, d3.max(categoriesArray)]) | |
.range([0, 420]); | |
// define bar charts to create the category widgets | |
// define variable that will be the D3 bar chart | |
let chart = d3.select('#box') | |
.selectAll("div") | |
.data(categories) | |
.style("width", function(d) { return x(d.value) + "px"; }) | |
.style("height", 20) | |
.style("background", '#9DE0AD') | |
.style('cursor','pointer') | |
.text(function(d) { | |
return d.name + ':' + commaSeparator(d.value); | |
}) | |
.on('click', function(d){ | |
source.setQuery(` | |
SELECT * FROM populated_places_spf | |
WHERE adm0name IN (\'${d.name}\'`) | |
}); | |
// exit | |
chart.exit().remove(); | |
// ENTER again, updates data | |
chart.enter() | |
.append("div") | |
.style("width", function(d) { return x(d.value) + "px"; }) | |
.style("height", 20) | |
.style("background", '#9DE0AD') | |
.style('cursor','pointer') | |
.text(function(d) { | |
return d.name + ':' + commaSeparator(d.value); | |
}) | |
.on('click', function(d){ | |
source.setQuery(` | |
SELECT * FROM populated_places_spf | |
WHERE adm0name = \'${d.name}\'` | |
) | |
}); | |
}); | |
// add category dataview to client | |
client.addDataview(categoryDataview); | |
// Set bounding box filter | |
const bboxFilter = new carto.filter.BoundingBoxLeaflet(map); | |
// add filter to formula dataview, so when the BBOX change, the formula data view will be recalculated | |
categoryDataview.addFilter(bboxFilter); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment