-
-
Save sabman/fe2e6b3224b5a3dfb6d6b92d8ff01011 to your computer and use it in GitHub Desktop.
leaflet.draw + CARTO
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>leaflet.draw + CARTO</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" /> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet-src.js"></script> | |
<link rel="stylesheet" href="https://libs.cartocdn.com/cartodb.js/v3/3.15/themes/css/cartodb.css" /> | |
<script src="https://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.3/leaflet.draw.css" /> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.3/leaflet.draw.js"></script> | |
<style> | |
html, body, #map { | |
height: 100%; | |
padding: 0; | |
margin: 0; | |
} | |
#infobox{ | |
width: 200px; | |
height: 200px; | |
position: absolute; | |
top: 20px; | |
left: 20px; | |
background-color: white; | |
opacity: 0.6; | |
text-align: center; | |
font-family: "Open Sans"; | |
} | |
</style> | |
</head> | |
<body> | |
<!-- map div --> | |
<div id="map"></div> | |
<!-- infobox div --> | |
<div id="infobox"> | |
<h4>Draw a geometry</h4> | |
<p id="count">Count</p> | |
<p id="total">Total</p> | |
<p id="avg">Average</p | |
</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 | |
a.* | |
FROM | |
populated_places a | |
</script> | |
<script> | |
function main() { | |
// get styles & query | |
const style = $("#style").text(), | |
query = $("#query").text(), | |
// declare map variable | |
map = L.map('map', { | |
zoomControl: false, | |
center: [41, -15], | |
zoom: 3 | |
}); | |
// add basemap | |
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="https://cartodb.com/attributions">CARTO</a>'}).addTo(map); | |
//prep the draw FeatureGroup and add Leaflet.draw controls to map | |
const editableLayers = new L.FeatureGroup(); | |
map.addLayer(editableLayers); | |
const drawPluginOptions = { | |
position: 'topright', | |
draw: { | |
polygon: { | |
allowIntersection: false, | |
drawError: { | |
color: '#46945C', | |
message: '<strong>Oh snap!<strong> you can\'t draw that!' | |
}, | |
shapeOptions: { | |
color: '#826DBA' | |
} | |
}, | |
polyline: false, | |
circle: false, | |
rectangle: false, | |
marker: false, | |
}, | |
edit: { | |
featureGroup: editableLayers, | |
remove: false | |
} | |
}; | |
const drawControl = new L.Control.Draw(drawPluginOptions); | |
map.addControl(drawControl); | |
// add CARTO layer | |
cartodb.createLayer(map, { | |
user_name: 'ramirocartodb', | |
type: 'cartodb', | |
sublayers: [{ | |
sql: query, | |
cartocss: style | |
}] | |
}).addTo(map) | |
.done(function(layer){ | |
// declare sublayer variable | |
const cityLayer = layer.getSubLayer(0); | |
// draw layer, intersect with CARTO layer & get count, total & avg data | |
map.on('draw:created', function(e) { | |
// draw layer | |
const drawLayer = e.layer; | |
editableLayers.addLayer(drawLayer); | |
// get geojson from the draw layer | |
const geojson = drawLayer.toGeoJSON(), | |
geom = JSON.stringify(geojson["geometry"]), | |
// set new query & style for intersected geometries | |
new_query = query + ` WHERE ST_Intersects(ST_SetSRID(ST_GeomFromGeoJSON('${geom}'), 4326), a.the_geom)`; | |
cityLayer.setSQL(new_query); | |
cityLayer.setCartoCSS('#layer {marker-width: 7; marker-fill: #FFFFFF; marker-fill-opacity: 0.9; marker-line-color: #EE4D5A; marker-line-width: 1; marker-line-opacity: 1; marker-type: ellipse; marker-allow-overlap: true;}'); | |
// get count, total and avg from intersected geometries | |
const sql = new cartodb.SQL({ user: 'ramirocartodb' }), | |
widget_query = `SELECT count(a.*) as count, sum(a.pop_max) as total, avg(a.pop_max) as avg FROM populated_places a WHERE ST_Intersects(ST_SetSRID(ST_GeomFromGeoJSON('${geom}'), 4326), a.the_geom)`; | |
sql.execute(widget_query) | |
.done(function(data) { | |
const count = JSON.stringify(data.rows[0].count), | |
total = JSON.stringify(data.rows[0].total), | |
avg = JSON.stringify(data.rows[0].avg); | |
// return count, total and avg in the infobox | |
$('#count').text(count); | |
$('#total').text(total); | |
$('#avg').text(avg); | |
}) | |
.error(function(errors) { | |
// errors contains a list of errors | |
console.log("errors:" + errors); | |
}) | |
// remove editable layer and clear parameters from the infobox when clicking on the draw layer | |
drawLayer.on('click', function(e){ | |
editableLayers.clearLayers(e.layer); | |
cityLayer.setSQL(query); | |
cityLayer.setCartoCSS(style); | |
// clear parameters from the infobox | |
$('#count').text('Count'); | |
$('#total').text('Total'); | |
$('#avg').text('Average'); | |
}); | |
}); | |
}); | |
} | |
window.onload = main; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment