Skip to content

Instantly share code, notes, and snippets.

@andy-esch
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andy-esch/515a8af1f99d5e690484 to your computer and use it in GitHub Desktop.
Save andy-esch/515a8af1f99d5e690484 to your computer and use it in GitHub Desktop.
Named map selectors with interaction

Webinar Write-up

Andy Eschbacher | Map Scientist | CartoDB | @MrEPhysics | eschbacher@cartodb.com

Find this document here: http://bit.ly/cdb-namedmaps

You can easily make Named Maps through the CartoDB Editor anytime you create a public visualization with your private data. Just because the visualization is public doesn't mean that your data is exposed. Only the data that is sent is the data that you configure ahead of time.

Making Named Maps in CartoDB.js is similar but requires more technical skills.

In this webinar we will make a Named Map with interactivity (click events to show infowindows) and SQL querying to expose different, pre-set information about your data. With these maps you can be confident that you have control over your data.

Getting Started

You need two files and access to a command line interface (such as Terminal on Mac) to make authenticated calls to create, update, list, or delete your Named Maps configurations.

The two files are listed in this gist: index.html and webinar-config.json.

You'll also need to grab your API Key.

webinar-config.json

This file (located below) sets up the configuration (SQL and CartoCSS) of your map on the server, similar to what you would see in a viz.json or a layer you set up on the fly in createLayer

index.html

This is an HTML document (located on the current page) that sets up your map on a webpage. You have limited control over how your map looks based on how restrictive you set up your map in your config file. Most CartoDB.js methods work with named maps just as they would with maps with public datasets.

The data

I'm using a dataset of found meteorites around the world. Directly import the dataset into your CartoDB account by copying the following URL and pasting it into the Importer.

http://andye.cartodb.com/api/v2/sql?q=SELECT%20*%20FROM%20meteorites_copy&filename=meteorite&format=csv

Command-line calls

Set up your map with the following statement:

curl 'https://{your_account_name}.cartodb.com/api/v1/map/named?api_key={your_api_key}' \
  -H 'Content-Type: application/json' \
  -d @webinar-config.json

In the config file

Multiple Layers

There is an array of layers, each one an object.

"layers": [
    {
        "options": {
            "cartocss": "#meteorites{ marker-fill: #5CA2D1; marker-width: 10; marker-line-color: #FFF; marker-line-width: 0; marker-line-opacity: 1; marker-fill-opacity: 0.6; marker-comp-op: multiply; marker-type: ellipse; marker-placement: point; marker-allow-overlap: true; marker-clip: false; marker-multi-policy: largest; }",
            "cartocss_version": "2.1.1",
            "interactivity": [
                "cartodb_id",
                "mass"
            ],
            "sql": "SELECT * FROM meteorites WHERE <%= layer0 %> = 1 AND mass <= 900000"
        },
        "type": "cartodb"
    },
    ...
    ]

SQL

SELECT * FROM meteorites WHERE <%= layer1 %> = 1 AND mass > 900000 AND mass <= 20000000

CartoCSS

#meteorites{ marker-fill: #F84F40; marker-width: 10; marker-line-color: #FFF; marker-line-width: 0; marker-line-opacity: 1; marker-fill-opacity: 0.6; marker-comp-op: multiply; marker-type: ellipse; marker-placement: point; marker-allow-overlap: true; marker-clip: false; marker-multi-policy: largest; }

Placeholder parameters: layerX

There are special placeholder values layer0, layer1, etc. that allow you to toggle sublayers on or off using sublayer.toggle() (or .hide() or .show()).

By setting them as parameters in your config file and placing them into your SQL you can give client-side control over which layers are shown or hidden.

name

This is the name of the map, where the meaning of "named maps" comes from.

HTML File

Most important piece of JavaScript:

cartodb.createLayer(map, {
    user_name: '{your account name}',
    type: 'namedmap',
    named_map: {
        name: "{name of named map}",
        layers: [{
            layer_name: "small_mass",
            interactivity: "{columns selected for interactivity}"
        },
        {
            layer_name: "medium_mass",
            interactivity: "cartodb_id, mass"
        },
        {
            layer_name: "large_mass",
            interactivity: "cartodb_id, mass"
        }]
     }
}).addTo(map)

Other things to notice

The function createSelector does the toggling of the data sublayers.

Final map should look like the map at the top of this page

More information

For more information, check out the Maps API documentation, our new Named Maps tutorial, and the CartoDB.js docs.

<!DOCTYPE html>
<html>
<head>
<title>Named Maps Webinar | CartoDB</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="http://cartodb.com/assets/favicon.ico" />
<style>
html, body, #map {
height: 100%;
padding: 0;
margin: 0;
}
#layers {
position: absolute;
top: 20px;
right: 20px;
}
.layer_selector {
background: rgba(255,255,255,0.9);
border-radius: 5px;
padding: 0;
border: 1px solid #999;
width: 250px;
}
.layer_selector > p {
padding: 15px 30px;
border-bottom: 1px solid #999;
}
.layer_selector ul {
padding: 0; margin: 0;
list-style-type: none;
}
.layer_selector li {
padding: 15px 30px;
font-family: Helvetica, Arial;
font-size: 13px;
color: #444;
cursor: pointer;
}
.layer_selector li:not(:last-child) {
border-bottom: 1px solid #999;
}
.layer_selector li:hover {
background-color: #F0F0F0;
cursor: pointer;
}
.layer_selector li.selected {
background-color: #A6CEE3;
}
</style>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.css" />
</head>
<body>
<div id="map"></div>
<div id="layers" class="layer_selector">
<p>Meteor Mass Selector</p>
<ul>
<li data="0">Show all meteorites with mass below 900000 g
</li>
<li data="1">Show meteorites with mass between 900000 g and 20000000 g
</li>
<li data="2">Show meteorites with mass above 20000000 g
</li>
<li data="-1">Show all
</li>
</ul>
</div>
<!-- include cartodb.js library -->
<script src="http://libs.cartocdn.com/cartodb.js/v3/cartodb.js"></script>
<!-- Drop your code between the script tags below! -->
<script>
function main() {
// create leaflet map
var map = L.map('map', {
zoomControl: false,
scrollWheelZoom: false,
center: [0, 0],
zoomControl: true,
zoom: 3
});
// add a base layer
L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
}).addTo(map);
function createSelector(layer) {
var layerchosen = "";
var $options = $(".layer_selector").find("li");
$options.click(function(e) {
var $li = $(e.target);
var selected = +$li.attr('data');
$options.removeClass('selected');
$li.addClass('selected');
if (selected !== -1) {
for (var i = 0; i < layer.getSubLayerCount(); i++) {
if (i !== selected) {
layer.getSubLayer(i).hide();
} else {
layer.getSubLayer(i).show();
}
}
} else {
for (var i = 0; i < layer.getSubLayerCount(); i++) {
layer.getSubLayer(i).show();
}
}
});
}
// add cartodb layer with one sublayer
cartodb.createLayer(map, {
user_name: 'andye',
type: 'namedmap',
named_map: {
name: "webinar_namedmaps_sample",
layers: [{
layer_name: "small_mass",
interactivity: "cartodb_id, mass"
},
{
layer_name: "medium_mass",
interactivity: "cartodb_id, mass"
},
{
layer_name: "large_mass",
interactivity: "cartodb_id, mass"
}]
}
})
.addTo(map)
.done(function(layer) {
// for all layers...
for (var i = 0; i < layer.getSubLayerCount(); ++i ) {
// turn on interaction
layer.getSubLayer(i).setInteraction(true);
// show infowindows on click
cdb.vis.Vis.addInfowindow(map, layer.getSubLayer(i), ['mass']);
// show data in console on mouseover
layer.getSubLayer(0).on('featureOver', function(e, pos, pixel, data) {
// print data to console log
console.log("Event #" + data.cartodb_id + ", mass " + data.mass);
});
}
createSelector(layer);
});
}
window.onload = main;
</script>
</body>
</html>
{
"auth": {
"method": "open"
},
"layergroup": {
"layers": [
{
"options": {
"cartocss": "#meteorites{ marker-fill: #5CA2D1; marker-width: 10; marker-line-color: #FFF; marker-line-width: 0; marker-line-opacity: 1; marker-fill-opacity: 0.6; marker-comp-op: multiply; marker-type: ellipse; marker-placement: point; marker-allow-overlap: true; marker-clip: false; marker-multi-policy: largest; }",
"cartocss_version": "2.1.1",
"interactivity": [
"cartodb_id",
"mass"
],
"sql": "SELECT * FROM meteorites WHERE <%= layer0 %> = 1 AND mass <= 900000"
},
"type": "cartodb"
},
{
"options": {
"cartocss": "#meteorites{ marker-fill: #FFCC00; marker-width: 10; marker-line-color: #FFF; marker-line-width: 0; marker-line-opacity: 1; marker-fill-opacity: 0.6; marker-comp-op: multiply; marker-type: ellipse; marker-placement: point; marker-allow-overlap: true; marker-clip: false; marker-multi-policy: largest; }",
"cartocss_version": "2.1.1",
"interactivity": [
"cartodb_id",
"mass"
],
"sql": "SELECT * FROM meteorites WHERE <%= layer1 %> = 1 AND mass > 900000 AND mass <= 20000000"
},
"type": "cartodb"
},
{
"options": {
"cartocss": "#meteorites{ marker-fill: #F84F40; marker-width: 10; marker-line-color: #FFF; marker-line-width: 0; marker-line-opacity: 1; marker-fill-opacity: 0.6; marker-comp-op: multiply; marker-type: ellipse; marker-placement: point; marker-allow-overlap: true; marker-clip: false; marker-multi-policy: largest; }",
"cartocss_version": "2.1.1",
"interactivity": [
"cartodb_id",
"mass"
],
"sql": "SELECT * FROM meteorites WHERE <%= layer2 %> = 1 AND mass > 20000000"
},
"type": "cartodb"
}
]
},
"name": "webinar_namedmaps_sample",
"placeholders": {
"layer0": {
"default": 1,
"type": "number"
},
"layer1": {
"default": 1,
"type": "number"
},
"layer2": {
"default": 1,
"type": "number"
}
},
"version": "0.0.1"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment