I'm trying to make one map where you can toggle between three different layers, and keep the same legend visible for all. I'm currently following this documentation:
http://docs.cartodb.com/tutorials/toggle_map_view.html
My map in CartoDB has three separate layers (w/ three datasets for the years 2013, 2014 and 2015).
I'm trying to make a toggle map like the one in the documentation. Here's what I go so far:
<html>
<head>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.11/themes/css/cartodb.css" />
<script src="http://libs.cartocdn.com/cartodb.js/v3/3.11/cartodb.js"></script>
<style>
html, body {width:100%; height:100%; padding: 0; margin: 0;}
#map { width: 100%; height:100%; background: black;}
#menu { position: absolute; top: 5px; right: 10px; width: 400px; height:60px; background: transparent; z-index:10;}
#menu a {
margin: 15px 10px 0 0;
float: right;
vertical-align: baseline;
width: 70px;
padding: 10px;
text-align: center;
font: bold 11px "Helvetica",Arial;
line-height: normal;
color: #555;
border-radius: 4px;
border: 1px solid #777777;
background: #ffffff;
text-decoration: none;
cursor: pointer;
}
#menu a.selected,
#menu a:hover {
color: #F84F40;
}
</style>
<script>
var map;
function init(){
// initiate leaflet map
map = new L.Map('map', {
center: [20,-20],
zoom: 3
})
L.tileLayer('https://dnv9my2eseobd.cloudfront.net/v3/cartodb.map-4xtxp73f/{z}/{x}/{y}.png', {
attribution: 'Mapbox <a href="http://mapbox.com/about/maps" target="_blank">Terms & Feedback</a>'
}).addTo(map);
var layerUrl = 'http://heathermartino.cartodb.com/api/v2/viz/415f8ed2-d493-11e4-b129-0e018d66dc29/viz.json';
var sublayers = [];
cartodb.createLayer(map, layerUrl)
.addTo(map)
.on('done', function(layer) {
// change the query for the first layer
var subLayerOptions = {
sql: "SELECT * FROM gdp_2014",
cartocss: "#gdp_2014{marker-fill: #F84F40; marker-width: 8; marker-line-color: white; marker-line-width: 2; marker-clip: false; marker-gdp_2015ow-overlap: true;}"
}
var sublayer = layer.getSubLayer(0);
sublayer.set(subLayerOptions);
sublayers.push(sublayer);
}).on('error', function() {
//log the error
});
//we define the queries that will be performed when we click on the buttons, by modifying the SQL of our layer
var LayerActions = {
GDP_2015: function(){
sublayers[0].setSQL("SELECT * FROM gdp_2015");
return true;
},
GDP_2014: function(){
sublayers[0].setSQL("SELECT * FROM gdp_2014");
return true;
},
GDP_2013: function() {
sublayers[0].set({
sql: "SELECT * FROM gdp_2013 WHERE cartodb_georef_status = true",
//as it is said, you can also add some CartoCSS code to make your points look like you want for the different queries
// cartocss: "#ne_10m_populated_places_simple{ marker-fill: black; }"
});
return true;
}
}
$('.button').click(function() {
$('.button').removeClass('selected');
$(this).addClass('selected');
//this gets the id of the different buttons and cgdp_2015s to LayerActions which responds according to the selected id
LayerActions[$(this).attr('id')]();
});
L.tileLayer('https://dnv9my2eseobd.cloudfront.net/v3/cartodb.map-4xtxp73f/{z}/{x}/{y}.png', {
attribution: 'Mapbox <a href="http://mapbox.com/about/maps" target="_blank">Terms & Feedback</a>'
}).addTo(map);
}
</script>
</head>
<body onload="init()">
<div id='map'></div>
<div id='menu'>
<a href="#gdp_2013" id="gdp_2013" class="button gdp_2013">2013</a>
<a href="#gdp_2014" id="gdp_2014" class="button gdp_2014">2014</a>
<a href="#gdp_2015" id="gdp_2015" class="button gdp_2015">2015</a>
</div>
</body>
</html>
Right now when you click on the different buttons for 2013, 2014 and 2015, nothing happens. For reference, my map in carto is http://cdb.io/1Bzm2tD. Any ideas? Thanks in advance!
You have the layers. No need to run SQL again. This should work.
<html>
<head>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.11/themes/css/cartodb.css" />
<script src="http://libs.cartocdn.com/cartodb.js/v3/3.11/cartodb.js"></script>
<style>
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#map {
width: 100%;
height: 100%;
background: black;
}
#menu {
position: absolute;
top: 5px;
right: 10px;
width: 400px;
height: 60px;
background: transparent;
z-index: 10;
}
#menu a {
margin: 15px 10px 0 0;
float: right;
vertical-align: baseline;
width: 70px;
padding: 10px;
text-align: center;
font: bold 11px "Helvetica", Arial;
line-height: normal;
color: #555;
border-radius: 4px;
border: 1px solid #777777;
background: #ffffff;
text-decoration: none;
cursor: pointer;
}
#menu a.selected,
#menu a:hover {
color: #F84F40;
}
.cartodb-layer-selector-box,
.cartodb-searchbox,
.cartodb-share {
display: none !important;
}
</style>
<script>
var layer;
function init() {
var url = 'http://heathermartino.cartodb.com/api/v2/viz/415f8ed2-d493-11e4-b129-0e018d66dc29/viz.json';
var visualizacion = cartodb.createVis("map", url)
.done(function(vis, layers) {
layer = layers[1];
});
}
function showLayer(layerToShow) {
//turn off all layers
layer.getSubLayers().forEach(function(i) {
i.hide()
});
switch (layerToShow.id) {
case "gdp_2013":
layer.getSubLayer(0).show();
break;
case "gdp_2014":
layer.getSubLayer(1).show();
break;
case "gdp_2015":
layer.getSubLayer(2).show();
break;
}
return true;
}
</script>
</head>
<body onload="init()">
<div id='map'></div>
<div id='menu'>
<a href="#gdp_2013" id="gdp_2013" class="button gdp_2013" onclick="showLayer(this);">2013</a>
<a href="#gdp_2014" id="gdp_2014" class="button gdp_2014" onclick="showLayer(this);">2014</a>
<a href="#gdp_2015" id="gdp_2015" class="button gdp_2015" onclick="showLayer(this)">2015</a>
</div>
</body>
</html>
I have created something similar - see if this helps. The trick for me was getting the sublayers separated with a for loop, then creating the buttons to act on each.
function loadPosition(position) {
lati = position.coords.latitude;
longi = position.coords.longitude;
map = L.map('map', {zoomControl: false}).setView([lati, longi], 15);
L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {maxZoom: 19,}).addTo(map);
L.control.scale({position: 'bottomright'}).addTo(map);
/*CARTODB LAYERS*/
var layerSource = {
user_name: 'YOUR USER NAME',
type: 'cartodb',
cartodb_logo: false,
sublayers: [{
sql: "SELECT * FROM winston_survey_tool WHERE point_class LIKE 'Orientation point'",
cartocss: '#winston_survey_tool{marker-fill:#D94C38;marker-opacity:1;line-color:#FFF;line-width:1;line-opacity:1;marker-allow-overlap:true; [zoom >= 15] {marker-width: 15} [zoom >= 19] {marker-width: 20}}'
},
{
sql: "SELECT * FROM winston_survey_tool WHERE point_class LIKE 'Survey point'",
cartocss: '#winston_survey_tool{marker-fill:#E0D03D;marker-opacity:1;line-color:#FFF;line-width:1;line-opacity:1;marker-allow-overlap:true; [zoom >= 15] {marker-width: 15} [zoom >= 19] {marker-width: 20}}'
}]
};
// STORE SUBLAYERS
var sublayers = [];
// ADD LAYER TO MAP
cartodb.createLayer(map,layerSource)
.addTo(map)
.done(function(layer) {
// SEPARATE THE SUBLAYERS
for (i = 0; i < layer.getSubLayerCount(); i++) {
sublayers[i] = layer.getSubLayer(i);
sublayers[i].hide();
};
// BUTTONS
$('#orientationCheck').click(function () {
orientationValue = $("#orientationCheck").val();
var query = "SELECT * FROM winston_survey_tool WHERE date LIKE'%";
yearSelectVal = $("#yearSelect").val();
query = query + yearSelectVal + "' AND point_class LIKE 'Orientation point'";
sublayers[0] = sublayers[0].setSQL(query);
if(orientationValue=="ON"){
sublayers[0].hide();
$('#orientationCheck').val("OFF");
$("#orientationCheck").addClass("off");
}
else{
sublayers[0].show();
$('#orientationCheck').val("ON");
$("#orientationCheck").removeClass("off");
};
});
$('#surveyCheck').click(function () {
surveyValue = $("#surveyCheck").val();
var query = "SELECT * FROM winston_survey_tool WHERE date LIKE'%";
yearSelectVal = $("#yearSelect").val();
query = query + yearSelectVal + "' AND point_class LIKE 'Survey point'";
sublayers[1] = sublayers[1].setSQL(query);
if(surveyValue=="ON"){
sublayers[1].hide();
$('#surveyCheck').val("OFF");
$("#surveyCheck").addClass("off");
}
else{
sublayers[1].show();
$('#surveyCheck').val("ON");
$("#surveyCheck").removeClass("off");
};
});
});