I am new to Leaflet and JavaScript. I am trying to create a web map that will have 3-4 buttons that when clicked will zoom the user to the given location. Ex: Disney World (28.385384005128767, -81.56313371302178), Black Pool Pleasure Beach (53.937909193096296, -3.0415772052368952).
So far, I have been trying code from a tutorial, but cannot get the buttons to show on my map. What am I doing wrong?
.full {
padding: 0;
margin: 0;
}
.full html, body, #map {
height: 100%;
width: 100vw;
}
.center {
text-align: center;
}
html, body, #map {
height: 100%;
width: 100vw;
}
#map{ width: 100%; height: 100%; }
iframe{
align-content: center;
width: 98%; height: 97%;
}
.leaflet-bar button,
.leaflet-bar button:hover {
background-color: #fff;
border: none;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar button {
background-position: 50% 50%;
background-repeat: no-repeat;
overflow: hidden;
display: block;
}
.leaflet-bar button:hover {
background-color: #f4f4f4;
}
.leaflet-bar button:first-of-type {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar button:last-of-type {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar.disabled,
.leaflet-bar button.disabled {
cursor: default;
pointer-events: none;
opacity: .4;
}
.easy-button-button .button-state{
display: block;
width: 100%;
height: 100%;
position: relative;
}
.leaflet-touch .leaflet-bar button {
width: 30px;
height: 30px;
line-height: 30px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> Map</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.3/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.0.3/dist/leaflet.js"></script>
<link rel="stylesheet" href="Leaflet.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet-easybutton#2/src/easy-button.css">
<script src="https://cdn.jsdelivr.net/npm/leaflet-easybutton#2/src/easy-button.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>
<body id ="full" class= "full">
<div id = "text">
</div>
<div id="map"></div>
<script>
var map = L.map('map',{ center: [42.353770, -71.10360608], zoom: 16, keyboard: true});
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap' }).addTo(map);
var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
}).addTo(map);
var OSM = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap' }).addTo(map);
var mapChoices = {
"Satellite": Esri_WorldImagery,
"OSM": OSM
}
L.control.layers(mapChoices).addTo(map);
</script>
<script>
var map = L.map('map', {scrollWheelZoom: false}).setView([37.8, -96], 4);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(zoomTo);
L.easyButton( 'fa-gbp', function(){
map.setView([55, -2], 4);
}).addTo(map);
L.easyButton( 'fa-jpy', function(){
map.setView([38, 139], 4);
}).addTo(map);
L.easyButton( 'fa-usd', function(){
map.setView([37.8, -96], 3);
}).addTo(map);
</script>
</body>
</html>
Simply do not re-instantiate your map and do not re-assign your map variable.
You can merge your 2 <script> tags together, it should become more obvious to you what the issue is.
Your 2nd map instantiation should throw an error in your browser Devtools console (if you are not using it, make sure to learn how to open it)
After that the rest of your script is ignored.
Related
do you know how to change background color. i tried using
body.darkmode{
background-color:black;
color: white;
still not working. my code is also very messy because i just started coding in html yesterday. so this is my first time. i'm tring to make a darkmode version. so please dont worry about the content because it just for demonstration. i also make the simmilar post yesterday, but in this case i put some scroll bar and navbar.
<!DOCTYPE html>
<html>
<head>
<title>UwU</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
#navbar a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 15px;
text-decoration: none;
font-size: 17px;
}
#navbar a:hover {
background-color: #ddd;
color: black;
}
</style>
</head>
<body>
<div style="padding:15px 15px 2500px;font-size:15px">
<script>
// When the user scrolls down 20px from the top of the document, slide down the navbar
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
document.getElementById("navbar").style.top = "0";
} else {
document.getElementById("navbar").style.top = "-50px";
}
}
</script>
<style>
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
.topnav {
overflow: hidden;
background-color: #333;
}
.topnav a {
float: left;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.topnav a.active {
background-color: #4CAF50;
color: white;
}
</style>
</head>
<body>
<div class="topnav">
<a class="active" href="#home">Home</a>
News
Contact
Settings
</div>
<style>
h1 {text-align: center;}
p {text-align: left;}
div {text-align: left;}
.left {
display: block;
margin-left: auto;
margin-right: auto;
}
</style>
</head>
<body>
<h1>UwU</h1>
<p>you just got uwu.</p>
<p>say uwu after you saw master uwu for ton of luck UwU</p>
<div>UwU.</div>
<p></p>
<img src="data:image/jpeg;base64,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" alt="avatar" style="width:300px">
</body>
</html>
<style type ="text/css" >
.footer{
position: fixed;
text-align: left;
bottom: 0px;
width: 100%;
color: black;
}
</style>
</head>
<body>
<div class="footer">Made by rama 4/6/2020
<br>use light mode<a>•••</a>Page 2 UwU
</div>
</body>
You have not added class = "darkmode" to the body tag.
Add this and it should work.
<body class = "darkmode">
I'm needing to add a collapsible sidebar to a mapbox map.
I'm using this example:
https://www.w3schools.com/howto/howto_js_collapse_sidebar.asp
Here is my html file. It shows it load briefly, but then the map renders on top of it.
Ultimately I want to develop a sidebar like what pops up when you click on a feature in Google Maps. I've not quite found something like this, so if anyone knows of a solution, let me know.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Castello Plan: Sidebar</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<!-- For Interactive sidebar Head-->
<style>
body {
font-family: "Lato", sans-serif;
}
.sidebar {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidebar a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s;
}
.sidebar a:hover {
color: #f1f1f1;
}
.sidebar .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
.openbtn {
font-size: 20px;
cursor: pointer;
background-color: #111;
color: white;
padding: 10px 15px;
border: none;
}
.openbtn:hover {
background-color: #444;
}
#main {
transition: margin-left .5s;
padding: 16px;
}
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
#media screen and (max-height: 450px) {
.sidebar {padding-top: 15px;}
.sidebar a {font-size: 18px;}
}
</style>
<!--End Interactive Sidebar Head-->
</head>
<body>
<div id='map'></div>
<!--For Interactive Sidebar Body-->
<div id="mySidebar" class="sidebar">
×
About
Services
Clients
Contact
</div>
<div id="main">
<button class="openbtn" onclick="openNav()">☰ Toggle Sidebar</button>
<h2>Collapsed Sidebar</h2>
<p>Click on the hamburger menu/bar icon to open the sidebar, and push this content to the right.</p>
</div>
<script>
function openNav() {
document.getElementById("mySidebar").style.width = "250px";
document.getElementById("main").style.marginLeft = "250px";
}
function closeNav() {
document.getElementById("mySidebar").style.width = "0";
document.getElementById("main").style.marginLeft= "0";
}
</script>
<!--End Interactive Sidebar Body-->
<script>
mapboxgl.accessToken = 'pk.eyJ1Ijoibml0dHlqZWUiLCJhIjoid1RmLXpycyJ9.NFk875-Fe6hoRCkGciG8yQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/nittyjee/cjowjzrig5pje2rmmnjb5b0y2',
center: [0, 0],
zoom: 0
});
</script>
</body>
</html>
Firstly, add your map to the main div, and set the map css to "position:relative;"
Your open button needed to also be "position:absolute;" and iven a z-depth of 1 tobe above the map.
I added 100% height to the html, body & map css to ensure the content stretches to full height.
Hope this helps.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Castello Plan: Sidebar</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map {
position: absolute;
top: 0; right: 0;
bottom: 0; left: 0;
width:100%;
height:100%;
}
html, body, #map{
height:100%;
margin: 0px;
}
.sidebar {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidebar a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s;
}
.sidebar a:hover {
color: #f1f1f1;
}
.sidebar .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
.openbtn {
font-size: 20px;
cursor: pointer;
background-color: #111;
color: white;
padding: 10px 15px;
border: none;
position:absolute;
top:10px;
left:10px;
z-index:1;
border-radius: 3px;
}
.openbtn:hover {
background-color: #444;
}
#main {
position:relative;
transition: margin-left .5s;
padding: 16px;
height:100%;
}
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
#media screen and (max-height: 450px) {
.sidebar {padding-top: 15px;}
.sidebar a {font-size: 18px;}
}
</style>
</head>
<body>
<!--For Interactive Sidebar Body-->
<div id="mySidebar" class="sidebar">
×
About
Services
Clients
Contact
</div>
<div id="main">
<button class="openbtn" onclick="openNav()">☰ Toggle Sidebar</button>
<div id='map'></div>
</div>
<script>
function openNav() {
document.getElementById("mySidebar").style.width = "250px";
document.getElementById("main").style.marginLeft = "250px";
}
function closeNav() {
document.getElementById("mySidebar").style.width = "0";
document.getElementById("main").style.marginLeft= "0";
}
</script>
<!--End Interactive Sidebar Body-->
<script>
mapboxgl.accessToken = 'pk.eyJ1Ijoibml0dHlqZWUiLCJhIjoid1RmLXpycyJ9.NFk875-Fe6hoRCkGciG8yQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/nittyjee/cjowjzrig5pje2rmmnjb5b0y2',
center: [0, 0],
zoom: 0
});
</script>
</body>
</html>
I am trying to create a choropleth that shades states depending on the rate of cases in 2010. I am getting the error: Uncaught TypeError: Cannot read property 'features' of null at Object.t.choropleth.n.exports [as choropleth]. Is this a problem with reading and extracting the data from the geojson?
var myMap = L.map('map', {
center: [39.8283, -98.5795],
zoom: 11
});
APIKEY = "pk.eyJ1Ijoic2NvdHRtY2FsaXN0ZXIxMyIsImEiOiJjamlhdWd2bzMxYjU1M3Ztcm54N2kxaDQ2In0.mGtR6lttrtiEpIqHVEIAtQ"
L.tileLayer("https://api.mapbox.com/styles/v1/mapbox/outdoors-v10/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoic2NvdHRtY2FsaXN0ZXIxMyIsImEiOiJjamlhdWd2bzMxYjU1M3Ztcm54N2kxaDQ2In0.mGtR6lttrtiEpIqHVEIAtQ").addTo(myMap)
var GEOLINK = "state_data_modified.geojson";
var geojson_0;
d3.json(GEOLINK, function(data){
geojson_0=L.choropleth(data, {
valueProperty: "Rate_2010",
scale: ['white', 'red'],
steps: 5,
mode: "q",
style:{
color:'#fff',
weight: 1,
fillOpacity: .8
},
onEachFeature: function(feature, layer){
layer.bindPopup(feature.properties.State + "<br>Number of cases:<br>" + feature.properties.Cases_2010)
}
}).addTo(myMap);
var legend = L.control({ position: "bottomright" });
legend.onAdd = function() {
var div = L.DomUtil.create("div", "info legend");
var limits = geojson.options.limits;
var colors = geojson.options.colors;
var labels = [];
// Add min & max
var legendInfo = "<h1>Cases and Rates</h1>" +
"<div class=\"labels\">" +
"<div class=\"min\">" + limits[0] + "</div>" +
"<div class=\"max\">" + limits[limits.length - 1] + "</div>" +
"</div>";
div.innerHTML = legendInfo;
limits.forEach(function(limit, index) {
labels.push("<li style=\"background-color: " + colors[index] + "\"></li>");
});
div.innerHTML += "<ul>" + labels.join("") + "</ul>";
return div;
};
legend.addTo(myMap);
});
body {
padding: 0;
margin: 0;
}
#map,
body,
html {
height: 100%;
}
.leaflet-popup-content {
text-align: center;
}
/* CSS from the Leaflet-Choropleth documentation */
.legend {
padding: 6px 8px;
font: 12px Arial, Helvetica, sans-serif;
font-weight: bold;
color: #555;
background: #fff;
background: rgba(255, 255, 255, 0.8);
border-radius: 5px;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
}
.legend ul {
padding: 0;
margin: 0;
clear: both;
list-style-type: none;
}
.legend li {
display: inline-block;
width: 30px;
height: 22px;
}
.legend .min {
float: left;
padding-bottom: 5px;
}
.legend .max {
float: right;
}
h1 {
text-align: center;
}
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<title>Test Choropleth</title>
<!-- Leaflet CSS & JS-->
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.2/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.0.2/dist/leaflet.js"></script>
<!-- d3 JavaScript -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<!-- Leaflet-Choropleth JavaScript -->
<script type="text/javascript" src="choropleth.js"></script>
<!-- Our CSS -->
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<!-- The div where we will inject our map -->
<div id="map"></div>
<script type="text/javascript" src="test_choro.js"></script>
</body>
</html>
picture of tilelayer and console
For me the error seem pretty clear.
You are loading your geojson from local storage: file:///Users...
This is not possible. You have to make it accessible from an url if you have a server (apache, nginx) or use github to get a raw file url.
You can also use this function:
$.getJSON("your_path/to/state_data.json", function(json) {
console.log(json);
});
There's an example of how to make a point draggable (which has a layer) and there's an example of how to setup a marker with a custom image, but how would I make that custom image draggable on the map when it doesn't have a layer associated with it?!
i came up with this from some another example i found, and mixed the two. It worked for what i wanted... I remember seeing this while looking for answers (a few times) so i came back to share.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Add custom icons with Markers</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
#marker6060 {
background-image: url('https://placekitten.com/g/60/60/');
background-size: cover;
width: 60px;
height: 60px;
border-radius: 50%;
cursor: pointer;
}
#marker5050 {
background-image: url('https://placekitten.com/g/50/50/');
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}
#marker4040 {
background-image: url('https://placekitten.com/g/40/40/');
background-size: cover;
width: 40px;
height: 40px;
border-radius: 50%;
cursor: pointer;
}
</style>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'YOURS, NOT MINE.';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [-65.017, -16.457],
zoom: 5
});
var element6060 = document.createElement('div');
element6060.id = 'marker6060';
var marker6060 = new mapboxgl.Marker({
element: element6060,
draggable: true,
color: '#000000'
})
.setLngLat([-66.324462890625, -16.024695711685304])
.addTo(map);
element6060.addEventListener('click', function() {
var message = 'Kitty 6060';
window.alert(message);
});
var element5050 = document.createElement('div');
element5050.id = 'marker5050';
var marker5050 = new mapboxgl.Marker({
element: element5050,
draggable: true,
color: '#000000'
})
.setLngLat([-61.2158203125, -15.97189158092897])
.addTo(map);
element5050.addEventListener('click', function() {
var message = 'Kitty 5050';
window.alert(message);
});
var element4040 = document.createElement('div');
element4040.id = 'marker4040';
var marker4040 = new mapboxgl.Marker({
element: element4040,
draggable: true,
color: '#000000'
})
.setLngLat([-63.29223632812499, -18.28151823530889])
.addTo(map);
element4040.addEventListener('click', function() {
var message = 'Kitty 4040';
window.alert(message);
});
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Add custom icons with Markers No Layer, Draggable</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
#marker6060 {
background-image: url('https://placekitten.com/g/60/60/');
background-size: cover;
width: 60px;
height: 60px;
border-radius: 50%;
cursor: pointer;
}
#marker5050 {
background-image: url('https://placekitten.com/g/50/50/');
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}
#marker4040 {
background-image: url('https://placekitten.com/g/40/40/');
background-size: cover;
width: 40px;
height: 40px;
border-radius: 50%;
cursor: pointer;
}
</style>
<div id='map'></div>
<script>
mapboxgl.accessToken = 'YOURS, NOT MINE.';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [-65.017, -16.457],
zoom: 5
});
var element6060 = document.createElement('div');
element6060.id = 'marker6060';
var marker6060 = new mapboxgl.Marker({
element: element6060,
draggable: true
})
.setLngLat([-66.324462890625, -16.024695711685304])
.addTo(map);
element6060.addEventListener('click', function() {
var message = 'Kitty 6060';
window.alert(message);
});
var element5050 = document.createElement('div');
element5050.id = 'marker5050';
var marker5050 = new mapboxgl.Marker({
element: element5050,
draggable: true
})
.setLngLat([-61.2158203125, -15.97189158092897])
.addTo(map);
element5050.addEventListener('click', function() {
var message = 'Kitty 5050';
window.alert(message);
});
var element4040 = document.createElement('div');
element4040.id = 'marker4040';
var marker4040 = new mapboxgl.Marker({
element: element4040,
draggable: true
})
.setLngLat([-63.29223632812499, -18.28151823530889])
.addTo(map);
element4040.addEventListener('click', function() {
var message = 'Kitty 4040';
window.alert(message);
});
</script>
</body>
</html>
</script>
</body>
</html>
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 Terms & Feedback'
}).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 Terms & Feedback'
}).addTo(map);
}
</script>
</head>
<body onload="init()">
<div id='map'></div>
<div id='menu'>
2013
2014
2015
</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'>
2013
2014
2015
</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");
};
});
});