Last active
February 26, 2018 02:51
-
-
Save rgdonohue/9185e7dcf6301054c64b3a3ae3551e20 to your computer and use it in GitHub Desktop.
CARTO 4.0 GUIDE Complete
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
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> | |
<title>CARTO GUIDE | NMP</title> | |
<meta name="viewport" content="initial-scale=1.0"> | |
<meta charset="utf-8"> | |
<link href="https://unpkg.com/[email protected]/dist/leaflet.css" rel="stylesheet"> | |
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700' rel='stylesheet' type='text/css'> | |
<style> | |
* { | |
margin: 0; | |
padding: 0; | |
} | |
html { | |
box-sizing: border-box; | |
height: 100%; | |
} | |
body { | |
background: #f2f6f9; | |
height: 100%; | |
font-family: "Open sans", Helvetica, Arial, sans-serif; | |
} | |
#container { | |
display: flex; | |
width: 100%; | |
height: 100%; | |
} | |
#map { | |
flex: 1; | |
margin: 10px; | |
} | |
#widgets { | |
width: 300px; | |
margin: 10px 10px 10px 0; | |
} | |
.widget { | |
background: white; | |
padding: 10px; | |
margin-bottom: 10px; | |
} | |
.widget h1 { | |
font-size: 1.2em; | |
} | |
.widget-formula .result { | |
font-size: 2em; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="container"> | |
<div id="map"></div> | |
<div id="widgets"> | |
<div id="countriesWidget" class="widget"> | |
<h1>European countries</h1> | |
<select class="js-countries"> | |
<option value="">All</option> | |
</select> | |
</div> | |
<div id="avgPopulationWidget" class="widget widget-formula"> | |
<h1>Average population</h1> | |
<p> | |
<span class="js-average-population result">xxx</span> inhabitants</p> | |
</div> | |
</div> | |
</div> | |
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script> | |
<script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/v4.0.0-beta.20/carto.min.js"></script> | |
<script> | |
const map = L.map('map').setView([50, 15], 4); | |
var client = new carto.Client({ | |
apiKey: '59f4929933b046edc4f8d4a9cfad1f33fe6f346c', | |
username: 'rgdonohue' | |
}); | |
// Adding 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: 10 | |
}).addTo(map); | |
// ** DEFINE DATASETS AND SOURCES ** | |
// countries as a dataset | |
const europeanCountriesDataset = new carto.source.Dataset(` | |
ne_adm0_europe | |
`); | |
// countries as a source | |
const populatedPlacesSource = new carto.source.SQL( | |
` | |
SELECT * | |
FROM ne_10m_populated_places_simple | |
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe) | |
` | |
) | |
// ** DEFINE carto styles ** | |
// countries styles | |
const europeanCountriesStyle = new carto.style.CartoCSS( | |
` | |
#layer { | |
polygon-fill: #162945; | |
polygon-opacity: 0.5; | |
::outline { | |
line-width: 1; | |
line-color: #FFFFFF; | |
line-opacity: 0.5; | |
} | |
} | |
` | |
); | |
// populated point locations styles | |
const populatedPlacesStyle = new carto.style.CartoCSS( | |
` | |
#layer { | |
marker-width: 8; | |
marker-fill: #FF583E; | |
marker-fill-opacity: 0.9; | |
marker-line-width: 0.5; | |
marker-line-color: #FFFFFF; | |
marker-line-opacity: 1; | |
marker-type: ellipse; | |
marker-allow-overlap: false; | |
} | |
` | |
) | |
// ** CREATE the carto layers ** | |
const europeanCountries = new carto.layer.Layer(europeanCountriesDataset, europeanCountriesStyle); | |
const populatedPlaces = new carto.layer.Layer(populatedPlacesSource, populatedPlacesStyle, { | |
featureOverColumns: ['name'] | |
}) | |
// d the carto layers ** | |
client.addLayers([europeanCountries, populatedPlaces]); | |
// add the carto client to the leaflet map | |
client.getLeafletLayer().addTo(map) | |
// ** ADD some UI stuff | |
// create a popup | |
const popup = L.popup({ | |
closeButton: false | |
}) | |
// when mousing over a feature of the pop places | |
populatedPlaces.on("featureOver", featureEvent => { | |
// change location of the popup | |
popup.setLatLng(featureEvent.latLng) | |
//if the popup isn't already open | |
if (!popup.isOpen()) { | |
// update the content and open on the map | |
popup.setContent(featureEvent.data.name).openOn(map) | |
} | |
}) | |
// remove the popup upon mousing out of feature | |
populatedPlaces.on("featureOut", featureEvent => { | |
popup.removeFrom(map) | |
}); | |
// create a new carto formula object (that does magical things? ) | |
const averagePopulation = new carto.dataview.Formula(populatedPlacesSource, 'pop_max', { | |
operation: carto.operation.AVG | |
}); | |
// when the avePop formula changes (presumably at least once upon initialization?) | |
averagePopulation.on('dataChanged', data => { | |
refreshAveragePopulationWidget(data.result); | |
}); | |
const countriesDataview = new carto.dataview.Category(europeanCountriesDataset, 'admin', { | |
limit: 100 | |
}); | |
countriesDataview.on('dataChanged', data => { | |
const countryNames = data.categories.map(category => category.name).sort(); | |
refreshCountriesWidget(countryNames); | |
}); | |
// ** ADD the new formula data views to the client | |
client.addDataview(averagePopulation); | |
client.addDataview(countriesDataview); | |
// any errors? | |
client.on('error', function (clientError) { | |
console.error(clientError.message) | |
}); | |
// ** APP FUNCTIONS ** | |
function refreshAveragePopulationWidget(avgPopulation) { | |
const widgetDom = document.querySelector('#avgPopulationWidget'); | |
const averagePopulationDom = widgetDom.querySelector('.js-average-population'); | |
averagePopulationDom.innerText = Math.floor(avgPopulation); | |
} | |
function refreshCountriesWidget(adminNames) { | |
// short cuts for selectors | |
const widgetDom = document.querySelector('#countriesWidget'); | |
const countriesDom = widgetDom.querySelector('.js-countries'); | |
countriesDom.onchange = event => { | |
const admin = event.target.value; | |
highlightCountry(admin); | |
filterPopulatedPlacesByCountry(admin); | |
}; | |
// Fill in the list of countries | |
adminNames.forEach(admin => { | |
const option = document.createElement('option'); | |
option.innerHTML = admin; | |
option.value = admin; | |
countriesDom.appendChild(option); | |
}); | |
} | |
function highlightCountry(admin) { | |
let cartoCSS = | |
` | |
#layer { | |
polygon-fill: #162945; | |
polygon-opacity: 0.5; | |
::outline { | |
line-width: 1; | |
line-color: #FFFFFF; | |
line-opacity: 0.5; | |
} | |
} | |
`; | |
if (admin) { | |
cartoCSS = | |
` | |
${cartoCSS} | |
#layer[admin!='${admin}'] { | |
polygon-fill: #CDCDCD; | |
} | |
`; | |
} | |
europeanCountriesStyle.setContent(cartoCSS); | |
} | |
function filterPopulatedPlacesByCountry(admin) { | |
let query = | |
` | |
SELECT * | |
FROM ne_10m_populated_places_simple | |
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe) | |
`; | |
if (admin) { | |
query = | |
` | |
SELECT * | |
FROM ne_10m_populated_places_simple | |
WHERE adm0name='${admin}' | |
`; | |
} | |
populatedPlacesSource.setQuery(query); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment