Initial commit
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
## Overview
|
||||
|
||||
CARTO.js lets you create custom location intelligence applications that leverage the power of the CARTO Platform.
|
||||
|
||||
### Audience
|
||||
|
||||
This documentation is designed for people familiar with JavaScript programming and object-oriented programming concepts. You should also be familiar with [Leaflet](https://leafletjs.com/) from a developer's point of view.
|
||||
|
||||
This conceptual documentation is designed to let you quickly start exploring and developing applications with the CARTO.js library. We also publish the [CARTO.js API Reference]({{site.cartojs_docs}}/reference/).
|
||||
|
||||
### Hello, World
|
||||
|
||||
The easiest way to start learning about the CARTO.js library is to see a simple example. The following web page displays a map adding a layer over it.
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Single layer | CARTO</title>
|
||||
<meta name="viewport" content="initial-scale=1.0">
|
||||
<meta charset="utf-8">
|
||||
<!-- Include Leaflet -->
|
||||
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
||||
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
|
||||
<!-- Include CARTO.js -->
|
||||
<script src="https://libs.cartocdn.com/carto.js/%VERSION%/carto.min.js"></script>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:600" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
|
||||
<link href="https://carto.com/developers/carto-js/examples/maps/public/style.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="map">
|
||||
</div>
|
||||
<!-- Description -->
|
||||
<aside class="toolbox">
|
||||
<div class="box">
|
||||
<header>
|
||||
<h1>Add a layer</h1>
|
||||
<button class="github-logo js-source-link"></button>
|
||||
</header>
|
||||
<section>
|
||||
<p class="description open-sans">Add one CARTO layer to your map.</p>
|
||||
</section>
|
||||
<footer class="js-footer"></footer>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<script>
|
||||
const map = L.map('map').setView([30, 0], 3);
|
||||
map.scrollWheelZoom.disable();
|
||||
|
||||
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18
|
||||
}).addTo(map);
|
||||
|
||||
const client = new carto.Client({
|
||||
apiKey: 'default_public',
|
||||
username: 'cartojs-test'
|
||||
});
|
||||
|
||||
const source = new carto.source.Dataset(`
|
||||
ne_10m_populated_places_simple
|
||||
`);
|
||||
const style = new carto.style.CartoCSS(`
|
||||
#layer {
|
||||
marker-width: 7;
|
||||
marker-fill: #EE4D5A;
|
||||
marker-line-color: #FFFFFF;
|
||||
}
|
||||
`);
|
||||
const layer = new carto.layer.Layer(source, style);
|
||||
|
||||
client.addLayer(layer);
|
||||
client.getLeafletLayer().addTo(map);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
[View example]({{site.cartojs_docs}}/examples/#example-add-a-layer).
|
||||
|
||||
Even in this simple example, there are a few things to note:
|
||||
|
||||
- We declare the application as HTML5 using the `<!DOCTYPE html>` declaration.
|
||||
- We load the CARTO.js library using a `script` tag.
|
||||
- We create a `div` element named "map" to hold the map.
|
||||
- We define the JavaScript that creates a map in the `div`.
|
||||
|
||||
These steps are explained below.
|
||||
|
||||
### Declaring your application as HTML5
|
||||
|
||||
We recommend that you declare a true DOCTYPE within your web application. Within the examples here, we've declared our applications as HTML5 using the simple HTML5 DOCTYPE as shown below:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
```
|
||||
|
||||
Most current browsers will render content that is declared with this DOCTYPE in "standards mode" which means that your application should be more cross-browser compliant. The DOCTYPE is also designed to degrade gracefully; browsers that don't understand it will ignore it, and use "quirks mode" to display their content.
|
||||
|
||||
We add styles to the map through the file `style.css`, declaring:
|
||||
|
||||
```css
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#map {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
```
|
||||
|
||||
This CSS declaration indicates that the map container <div> (with id map) should take up 100% of the height of the HTML body.
|
||||
|
||||
### Loading the CARTO.js library
|
||||
|
||||
To load the Maps JavaScript API, use a script tag like the one in the following example:
|
||||
|
||||
```html
|
||||
<script src="https://libs.cartocdn.com/carto.js/%VERSION%/carto.min.js"></script>
|
||||
```
|
||||
|
||||
The URL contained in the script tag is the location of a JavaScript file that loads all of the code you need for using the CARTO.js library. This script tag is required. We are using the minified version of the library.
|
||||
|
||||
**Tip:** If you have experience with **npm** and a build system in your project (webpack, rollup…), you can install CARTO.js library with `npm install @carto/carto.js`. Then you can import it easily with `import carto from '@carto/carto.js` (or `var carto = require('@carto/carto.js')`, depending on your module system).
|
||||
|
||||
|
||||
#### HTTPS or HTTP
|
||||
We think security on the web is pretty important, and recommend using HTTPS whenever possible. As part of our efforts to make the web more secure, we've made all of the CARTO components available over HTTPS. Using HTTPS encryption makes your site more secure, and more resistant to snooping or tampering.
|
||||
|
||||
We recommend loading the CARTO.js library over HTTPS using the `<script>` tag provided above.
|
||||
|
||||
### Map DOM Elements
|
||||
|
||||
```html
|
||||
<div id="map"></div>
|
||||
```
|
||||
|
||||
For the map to display on a web page, we must reserve a spot for it. Commonly, we do this by creating a named div element and obtaining a reference to this element in the browser's document object model (DOM).
|
||||
|
||||
In the example above, we used CSS to set the height of the map div to "100%". This will expand to fit the size on mobile devices. You may need to adjust the width and height values based on the browser's screensize and padding.
|
||||
|
||||
### Map options
|
||||
|
||||
In this example, we are using Leaflet to render the map:
|
||||
|
||||
```javascript
|
||||
const map = L.map('map').setView([30, 0], 3);
|
||||
```
|
||||
|
||||
The common options for every map are: `center` and `zoom`. In this case, we are setting these with [Leaflet's setView method](https://leafletjs.com/reference-1.3.0.html#map-setview).
|
||||
|
||||
#### Zoom Levels
|
||||
|
||||
The initial resolution at which to display the map is set by the zoom property, where zoom 0 corresponds to a map of the Earth fully zoomed out, and larger zoom levels zoom in at a higher resolution. Specify zoom level as an integer. In our case, we are setting up this as **3**.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
If your code isn't working:
|
||||
|
||||
- Look for typos. Remember that JavaScript is a case-sensitive language.
|
||||
- Check the basics. Some of the most common problems occur with the initial map creation. Such as:
|
||||
- Confirm that you've specified the zoom and center properties in your map options.
|
||||
- Ensure that you have declared a div element in which the map will appear on the screen.
|
||||
- Ensure that the div element for the map has a height.
|
||||
- Refer to our [examples]({{site.cartojs_docs}}/examples/) for a reference implementation.
|
||||
- Use a JavaScript debugger to help identify problems. Chrome Developer Tools is a good one.
|
||||
- Post questions to the [GIS Stack Exchange using the `CARTO` tag](https://gis.stackexchange.com/questions/tagged/carto). Guidelines on how to post great questions are available on the [support page]({{site.cartojs_docs}}/support/).
|
||||
@@ -0,0 +1,60 @@
|
||||
## Get API Key
|
||||
|
||||
To use the CARTO.js library, you must register your project in your CARTO account and get an API key which you can add to your app or website.
|
||||
|
||||
### Quick guide to getting a key
|
||||
|
||||
#### Step 1: Get an API Key from your CARTO account
|
||||
|
||||
Start creating your API key, [registering a project](https://carto.com/login) in the CARTO Platform.
|
||||
|
||||
Notes:
|
||||
|
||||
- **Tip**: During development and testing, you can register a project for testing purposes in the CARTO Platform and use a generic, unrestricted API key. When you are ready to move your app or website into production, register a separate project for production, create a restricted API key, and add the key to your application.
|
||||
- **Enterprise customers**: For production-ready apps, you must use a restricted API key.
|
||||
|
||||
For more information, see the [fundamentals about authorization]({{site.fundamental_docs}}/authorization/).
|
||||
|
||||
#### Step 2: Add the API key and username to your application
|
||||
|
||||
After loading the CARTO.js library, substitute YOUR_API_KEY in the code below with the API key you got from the previous step.
|
||||
|
||||
```javascript
|
||||
var client = new carto.Client({
|
||||
apiKey: '{YOUR_API_KEY}',
|
||||
username: '{username}'
|
||||
});
|
||||
```
|
||||
|
||||
You can get your username following these steps:
|
||||
|
||||
- Login into to your CARTO account.
|
||||
- Go to your account from the left menu.
|
||||
- Copy the username under the plan information.
|
||||
|
||||
#### More about API keys
|
||||
|
||||
The API key allows you to control your applications in the CARTO Platform.
|
||||
|
||||
If you are a Trial Plan customer, with an API key you have access to all the Engine features.
|
||||
|
||||
If you are an Engine Plan customer, you must use an API key to access all the custom features and benefits of your Engine Plan.
|
||||
|
||||
#### Detailed guide for users of the CARTO.js library
|
||||
|
||||
Follow these steps to get an API key:
|
||||
|
||||
- Go to your CARTO account.
|
||||
- Go to your API Keys dashboard.
|
||||
- Click "NEW API KEY" to create a new one.
|
||||
- If you want to manage projects, you can regenerate or delete them.
|
||||
- On the API key page, configure it giving a name and the APIs and Datasets you want to use.
|
||||
|
||||
For more information on using the CARTO Platform, see our [fundamentals]({{site.fundamental_docs}}/).
|
||||
|
||||
|
||||
#### Troubleshooting authorization issues
|
||||
|
||||
If your API key is malformed or you supply an invalid username, the CARTO.js library returns an HTTP 403 (Forbidden) error.
|
||||
|
||||
CARTO Enterprise customers have access to enterprise-level support through CARTO’s support representatives available at enterprise-support@carto.com.
|
||||
@@ -0,0 +1,408 @@
|
||||
## Quickstart Guide
|
||||
|
||||
CARTO.js lets you create custom location intelligence applications that leverage the power of the **[CARTO Engine](https://carto.com/pricing/engine/)** ecosystem.
|
||||
|
||||
This document details CARTO.js v4. To update your v3 apps, please consult the [Upgrade Considerations]({{site.cartojs_docs}}/guides/upgrade-considerations/).
|
||||
|
||||
### About this Guide
|
||||
|
||||
This guide describes how to create a Leaflet map and display data from CARTO over the map. This demonstrates how CARTO.js can be used to
|
||||
|
||||
1. Overlay Data from your CARTO account on any Map.
|
||||
2. Use Dataviews to Create Widgets.
|
||||
|
||||
|
||||
**Tip:** For more advanced documentation, view the [Full Reference API]({{site.cartojs_docs}}/reference/) or browse through some [examples]({{site.cartojs_docs}}/examples/). You can also read the [FAQs]({{site.cartojs_docs}}/support/faq/).
|
||||
|
||||
### Audience
|
||||
|
||||
This document is intended for website or mobile developers who want to include CARTO.js library within a webpage or mobile application. It provides an introduction to using the library and reference material on the available parameters.
|
||||
|
||||
### Requesting an API Key
|
||||
|
||||
CARTO.js requires using an API Key. From your CARTO dashboard, click [_Your API keys_](https://carto.com/login) from the avatar drop-down menu to view your uniquely generated API Key for managing data with CARTO Engine.
|
||||
|
||||
If you want learn more about authorization and authentication, read the [authorization fundamentals section]({{site.fundamental_docs}}/authorization/).
|
||||
|
||||
### Importing Datasets
|
||||
Before you start working on the map, you need to import a couple of datasets. For this guide, we will use CARTO's Data Library, available from *Your datasets* dashboard, to import and connect public datasets to your account.
|
||||
|
||||
Alternatively, click the following links to download datasets from a public CARTO account:
|
||||
|
||||
* [European countries (ne_adm0_europe)](https://carto.com/dataset/ne_adm0_europe)
|
||||
* [Populated places (ne_10m_populated_places_simple)](https://carto.com/dataset/ne_10m_populated_places_simple)
|
||||
|
||||
Once downloaded, import the datasets to your CARTO account.
|
||||
|
||||
### Setting up the Map
|
||||
|
||||
By the end of the lesson, you will have generated an HTML file of a Leaflet Map showing CARTO's Voyager basemap and labels on top.
|
||||
|
||||
#### Application Skeleton
|
||||
|
||||
Create an HTML file using your preferred text editor and paste the following code to build the application skeleton:
|
||||
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Guide | CARTO</title>
|
||||
<meta name="viewport" content="initial-scale=1.0">
|
||||
<meta charset="utf-8">
|
||||
<!-- Include Leaflet -->
|
||||
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
||||
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
|
||||
<!-- Include CARTO.js -->
|
||||
<script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/%VERSION%/carto.min.js"></script>
|
||||
<!-- Fonts -->
|
||||
<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>
|
||||
// code will go here!
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
The first part of the skeleton loads CARTO.js and Leaflet 1.2.0 assumes Leaflet is loaded in `window.L`. The library checks if the version of Leaflet is compatible. If not, it throws an error.
|
||||
|
||||
The app skeleton also loads CARTO.js, adds some necessary elements, and defines a `script` tag. This is where you will write all the JavaScript code to make the example work.
|
||||
|
||||
**Note:** While CARTO.js enables you to display data from CARTO on top of Leaflet or Google Maps map, the actual map settings are controlled via the [Leaflet](http://leafletjs.com/) or [Google Maps](https://hpneo.github.io/gmaps/) map options.
|
||||
|
||||
#### Creating the Leaflet Map
|
||||
|
||||
CARTO.js apps start from a Leaflet or Google Map. Let's use a basic [Leaflet](http://leafletjs.com/) map for this guide:
|
||||
|
||||
```javascript
|
||||
const map = L.map('map').setView([50, 15], 4);
|
||||
```
|
||||
|
||||
#### Adding Basemap and Label Layers
|
||||
|
||||
Define the type of basemap to be used for the background of your map. For this guide, let's use [CARTO's Voyager basemap](https://carto.com/location-data-services/basemaps/).
|
||||
|
||||
```javascript
|
||||
// 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);
|
||||
```
|
||||
|
||||
`L.tileLayer` creates a layer for the basemap and the `zIndex` property defines the basemap labels (that sit on top of the other layers).
|
||||
|
||||
### Defining a `carto.Client`
|
||||
|
||||
`carto.Client` is the entry point to CARTO.js. It handles the communication between your app and your CARTO account, which is defined by your API Key and your username.
|
||||
|
||||
```javascript
|
||||
var client = new carto.Client({
|
||||
apiKey: '{API Key}',
|
||||
username: '{username}'
|
||||
});
|
||||
```
|
||||
|
||||
**Warning:** Ensure that you modify any placeholder parameters shown in curly brackets with your own credentials. For example, `apiKey: '123abc',` and `username: 'john123'`.
|
||||
|
||||
### Displaying Data on the Map
|
||||
|
||||
Display data hosted on your CARTO account as map layers.
|
||||
|
||||
### Defining Layers
|
||||
|
||||
Layers are defined with `carto.layer.Layer` which include the dataset name and basic styling options with CartoCSS.
|
||||
|
||||
```javascript
|
||||
const europeanCountriesDataset = new carto.source.Dataset(`
|
||||
ne_adm0_europe
|
||||
`);
|
||||
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;
|
||||
}
|
||||
}
|
||||
`);
|
||||
const europeanCountries = new carto.layer.Layer(europeanCountriesDataset, europeanCountriesStyle);
|
||||
```
|
||||
The first layer defines a `carto.source.Dataset` object that points to the imported dataset named `ne_adm0_europe`. To style the layer, define a `carto.style.CartoCSS` object that describes how polygons will be rendered.
|
||||
|
||||
```javascript
|
||||
const populatedPlacesSource = new carto.source.SQL(`
|
||||
SELECT *
|
||||
FROM ne_10m_populated_places_simple
|
||||
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe)
|
||||
`);
|
||||
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;
|
||||
}
|
||||
`);
|
||||
const populatedPlaces = new carto.layer.Layer(populatedPlacesSource, populatedPlacesStyle, {
|
||||
featureOverColumns: ['name']
|
||||
});
|
||||
```
|
||||
|
||||
The second layer uses a more complex type of data source for the layer. `carto.source.SQL` provides more flexibility for defining the data that you want to display in a layer. For this guide, we are composing a `SELECT` statement that selects populated cities in Europe. (Optionally, you can change this query at runtime).
|
||||
|
||||
The `featureOverColumns: ['name']` option we include in the layer creation defines what columns of the datasource will be available in `featureOver` events as we explain below.
|
||||
|
||||
#### Adding Layers to the Client
|
||||
|
||||
Before you can add layers to the map, the `carto.Client` variable needs to be notified that these layers exist. The client is responsible for grouping layers into a single Leaflet layer.
|
||||
|
||||
```javascript
|
||||
client.addLayers([europeanCountries, populatedPlaces]);
|
||||
```
|
||||
|
||||
#### Adding Layers to the Map
|
||||
|
||||
Now that the client recognizes these two layers, this single Leaflet layer can be added to the map.
|
||||
|
||||
```javascript
|
||||
client.getLeafletLayer().addTo(map);
|
||||
```
|
||||
|
||||
As a result, your map should display polygons for each European country and red points represent populated cities.
|
||||
|
||||
**Tip:** In order to change the order of layers, flip the order from `([A, B]);` to `(B, A);`
|
||||
|
||||
### Setting up Tooltips
|
||||
|
||||
Tooltips give map viewers information about the underlying data as they interact with the map by clicking or hovering over data. CARTO.js provides a simple mechanism to detect some of these interactions and use the data associated to them. For this guide, let's display a mouse hover tooltip showing the name of a city.
|
||||
|
||||
#### Showing the Tooltip when User Mouses Over a City
|
||||
|
||||
Layers trigger `featureOver` events when the map viewer hovers the mouse over a feature. The event includes data about the feature, such as the latitude and longitude, as well as specified column values defined in `featureOverColumns`.
|
||||
|
||||
```javascript
|
||||
const popup = L.popup({ closeButton: false });
|
||||
populatedPlaces.on(carto.layer.events.FEATURE_OVER, featureEvent => {
|
||||
popup.setLatLng(featureEvent.latLng);
|
||||
if (!popup.isOpen()) {
|
||||
popup.setContent(featureEvent.data.name);
|
||||
popup.openOn(map);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
In this snippet, we are defining a `L.popup` and listening to the `featureOver` event. When the event is triggered, the pop-up is positioned, populated with the name of the city, and added to the map.
|
||||
|
||||
|
||||
#### Hiding the Tooltip
|
||||
|
||||
Similarly, layers trigger `featureOut` events when the map viewer is no longer moving the mouse over a feature. Use this event to hide the pop-up.
|
||||
|
||||
```javascript
|
||||
populatedPlaces.on(carto.layer.events.FEATURE_OUT, featureEvent => {
|
||||
popup.removeFrom(map);
|
||||
});
|
||||
```
|
||||
|
||||
When `featureOut` is triggered, this code removes the pop-up from the map.
|
||||
|
||||
### Creating a Country Selector Widget
|
||||
|
||||
This section describes how to get data from a previously defined data source and display a country selector the map. As a result, selecting a country on the map highlights the country and filters by populated places.
|
||||
|
||||
#### Defining a Category Dataview
|
||||
|
||||
Dataviews are the mechanism CARTO.js uses to access data from a data source (dataset or SQL query) in a particular way (eg: list of categories, result of a formula, etc.). Use the `carto.dataview.Category` dataview to get the names of the European countries in the dataset:
|
||||
|
||||
```javascript
|
||||
const countriesDataview = new carto.dataview.Category(europeanCountriesDataset, 'admin', {
|
||||
limit: 100
|
||||
});
|
||||
```
|
||||
|
||||
This type of dataview expects a data source and the name of the column with the categories. By default, results are limited. For this guide, we specified a limit of 100 categories to make sure all country names are returned.
|
||||
|
||||
#### Listening to Data Changes on the Dataview
|
||||
|
||||
In order to know when a dataview has new data (eg: right after it has been added to the client or when its source has changed), you should listen to the `dataChanged` event. This event gives you an object with all the categories.
|
||||
|
||||
```javascript
|
||||
countriesDataview.on('dataChanged', data => {
|
||||
const countryNames = data.categories.map(category => category.name).sort();
|
||||
refreshCountriesWidget(countryNames);
|
||||
});
|
||||
|
||||
function refreshCountriesWidget(adminNames) {
|
||||
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);
|
||||
}
|
||||
```
|
||||
|
||||
This snippet generates the list of country names in alphabetical order from the `dataChanged` parameter and uses the `SELECT` function to populate the list.
|
||||
|
||||
When a country is selected, two functions are invoked: `highlightCountry` (highlights the selected country by setting a new CartoCSS to the layer) and `filterPopulatedPlacesByCountry` (filters the cities by changing the SQL query).
|
||||
|
||||
#### Adding the Dataview to the Client
|
||||
|
||||
The dataview needs to be added to the client in order to fetch data from CARTO.
|
||||
|
||||
```javascript
|
||||
client.addDataview(countriesDataview);
|
||||
```
|
||||
|
||||
### Creating a Formula Widget
|
||||
|
||||
Now that you have a working country selector, let's add a widget that will display the average max population of the populated places for the selected country (or display ALL if no country is selected).
|
||||
|
||||
#### Defining a Formula Dataview
|
||||
|
||||
`carto.dataview.Formula` allows you to execute aggregate functions (count, sum, average, max, min) on a data source:
|
||||
|
||||
```javascript
|
||||
const averagePopulation = new carto.dataview.Formula(populatedPlacesSource, 'pop_max', {
|
||||
operation: carto.operation.AVG
|
||||
});
|
||||
```
|
||||
|
||||
The `averagePopulation` dataview triggers a `dataChanged` event every time a new average has been calculated.
|
||||
|
||||
#### Listening to Data Changes on the Dataview
|
||||
|
||||
The `dataChanged` event allows you to get results of the aggregate function and use it in many ways.
|
||||
|
||||
```javascript
|
||||
averagePopulation.on('dataChanged', data => {
|
||||
refreshAveragePopulationWidget(data.result);
|
||||
});
|
||||
|
||||
function refreshAveragePopulationWidget(avgPopulation) {
|
||||
const widgetDom = document.querySelector('#avgPopulationWidget');
|
||||
const averagePopulationDom = widgetDom.querySelector('.js-average-population');
|
||||
averagePopulationDom.innerText = Math.floor(avgPopulation);
|
||||
}
|
||||
```
|
||||
|
||||
This snippet refreshes the averaged population widget every time a new average is available (e.g., when a new country is selected).
|
||||
|
||||
#### Adding the dataview to the client
|
||||
|
||||
To get a full working dataview, add it to your client:
|
||||
|
||||
```javascript
|
||||
client.addDataview(averagePopulation);
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
<div class="example-map">
|
||||
<iframe src="{{site.cartojs_docs}}/guides/quickstart-example.html" width="100%" height="600" frameBorder="0" style="padding-top: 20px;padding-bottom: 0;" class="u-vspace--24"></iframe>
|
||||
<a href="{{site.cartojs_docs}}/guides/quickstart-example.html" class="buttonLink is-DocsGreen u-vspace--32" target="_blank">
|
||||
<svg width="8px" height="7px" viewbox="0 0 8 7" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path class="buttonLink-media" d="M1.52245273,3.04854764 L3.68776506,0.883235307 C3.88225492,0.688745449 3.88821988,0.353713791 3.68525771,0.15075162 C3.4882313,-0.0462747862 3.15435142,-0.053333131 2.95277402,0.148244267 L0.147793654,2.95322464 C0.0109867585,3.09003153 -0.0325396573,3.29637729 0.0243152648,3.47738142 C-0.0325396573,3.65838554 0.0109867585,3.8647313 0.147793654,4.00153819 L2.95277402,6.80651857 C3.15435142,7.00809596 3.4882313,7.00103762 3.68525771,6.80401121 C3.88821988,6.60104904 3.88225492,6.26601738 3.68776506,6.07152753 L1.70421948,4.08798194 L7.99996393,4.08798194 L7.99996393,3.04854764 L1.52245273,3.04854764 Z" id="Combined-Shape" fill="#1FAC06" transform="translate(3.999982, 3.477381) scale(-1, 1) translate(-3.999982, -3.477381) "/>
|
||||
</g>
|
||||
</svg>
|
||||
Click to open map full size
|
||||
</a>
|
||||
</div>
|
||||
|
||||
### Troubleshooting and support
|
||||
|
||||
For more information on using the CARTO.js library, take a look at the [support page]({{site.cartojs_docs}}/support/).
|
||||
|
||||
The CARTO.js library may issue an error or warning when something goes wrong. You should check for warnings in particular if you notice that something is missing. It's also a good idea to check for warnings before launching a new application. Note that the warnings may not be immediately apparent because they appear in the HTTP header. For more information, see the guide to [errors messages]({{site.cartojs_docs}}/support/error-messages/).
|
||||
|
||||
This guide is just an overview of how to use CARTO.js to overlay data and create widgets. View the [Examples]({{ site.cartojs_docs }}/examples/) section for specific features of CARTO.js in action.
|
||||
@@ -0,0 +1,101 @@
|
||||
## Performance Tips
|
||||
|
||||
As you go through developing your applications with CARTO.js, you might find useful some tips to ease the development and make your application more performant.
|
||||
|
||||
### Sources
|
||||
Sources are the objects to get data from. The source is the entity that points to the data we want to show in our layers or in a widget through a dataview.
|
||||
|
||||
When working with sources, you may want to change the actual query to show other data in your visualization or dataviews. The most common case is filtering your data. The layers and dataviews react to changes coming from linked sources, so that you don't have to create another source. Layers and dataviews that are linked to the source reflect the changes in the source.
|
||||
|
||||
The way to go is to call `.setQuery` method to update the SQL query when using a `carto.source.SQL`, or use `.setTableName` in a `carto.source.Dataset` source, like in this examples:
|
||||
|
||||
``` js
|
||||
const populationSource = new carto.source.SQL('SELECT * FROM your_dataset');
|
||||
populationSource.setQuery('SELECT * FROM your_dataset WHERE price < 80');
|
||||
```
|
||||
|
||||

|
||||
|
||||
``` js
|
||||
const populationDataset = new carto.source.Dataset('your_dataset');
|
||||
populationDataset.setTableName('another_dataset');
|
||||
```
|
||||
|
||||

|
||||
|
||||
That way, the dataviews and visualizations retrieving data from that source will be automatically updated without doing anything else on your part.
|
||||
|
||||
### Styles
|
||||
We need to use CartoCSS whenever we want to change the style of our markers or polygons, among other things. Each CartoCSS instance contains the styles we want to apply to any of our layers.
|
||||
|
||||
These style instances work the same way as sources do. It is pretty common to change styles in your map based on certain triggers, so that you can adequate your visualization to what you want to show.
|
||||
|
||||
When linked to a layer, it will automatically show the style change when invoking `.setContent` on the style object with a string containing the new style content.
|
||||
|
||||
```js
|
||||
const layerStyle = new carto.style.CartoCSS(`
|
||||
#layer {
|
||||
marker-width: 8;
|
||||
marker-fill: #FF583E;
|
||||
marker-fill-opacity: 0.9;
|
||||
marker-allow-overlap: false;
|
||||
}
|
||||
`);
|
||||
|
||||
layerStyle.setContent(`
|
||||
#layer {
|
||||
marker-width: 10;
|
||||
marker-fill: #FF583E;
|
||||
marker-allow-overlap: true;
|
||||
}
|
||||
`);
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Layers
|
||||
Layers are a fundamental part of your CARTO.js application. They show the data of a source using the style of a CartoCSS.
|
||||
|
||||
As stated before, the layer will be automatically updated in the map when any of its properties (source and style) change.
|
||||
|
||||
So, let's say that you want to update the table of your visualization which had been created like this:
|
||||
|
||||
``` js
|
||||
const populationSource = new carto.source.SQL('SELECT * FROM your_dataset');
|
||||
const layerStyle = new carto.style.CartoCSS(`
|
||||
#layer {
|
||||
marker-width: 10;
|
||||
marker-fill: #FF583E;
|
||||
marker-allow-overlap: true;
|
||||
}
|
||||
`);
|
||||
|
||||
const layer = new carto.layer.Layer(populationSource, layerStyle);
|
||||
```
|
||||
|
||||
To update the visualization, the only thing you need to do is to invoke `.setQuery` in your source and everything will be refreshed accordingly.
|
||||
|
||||
```js
|
||||
populationSource.setQuery('SELECT * FROM your_dataset WHERE price > 500');
|
||||
```
|
||||
|
||||
### Dataviews
|
||||
Dataviews are a way to extract data from our source in predefined ways depending on the type of the column (eg: a list of categories, the result of a formula operation, etc...).
|
||||
|
||||
Dataviews need a source to extract data from. So when a source is passed to a dataview, it will react to the changes happening to the source, whether changing the query or adding filters.
|
||||
|
||||
```js
|
||||
const populatedPlaces = new carto.source.Dataset('ne_10m_populated_places_simple');
|
||||
|
||||
const column = 'adm0name'; // Aggregate the data by country.
|
||||
const categoryDataview = new carto.dataview.Category(populatedPlaces, column, {
|
||||
operation: carto.operation.AVG, // Compute the average
|
||||
operationColumn: 'pop_max' // The name of the column where the operation will be applied.
|
||||
});
|
||||
|
||||
// ...
|
||||
|
||||
citiesSource.addFilter(new carto.filter.Category(column, { eq: 'Spain' } ));
|
||||
```
|
||||
|
||||
In the example above, first we set a dataview getting data from a dataset with information about populated places. Then, we add a filter to the source to show only data coming from Spain. As you can see, we've updated the source and since the dataview was created linked to that source, a change on the query makes the dataview to react to that change automatically. There's no need to create another source and then another dataview.
|
||||
@@ -0,0 +1,181 @@
|
||||
## Upgrade Considerations Guide
|
||||
|
||||
This document is intended for existing developers who have used [previous versions]({{site.cartojs_docs}}/reference/#versioning) of CARTO.js.
|
||||
|
||||
### About this Guide
|
||||
|
||||
This guide describes how the CARTO.js library has changed to support additional functionality. It outlines the basic workflow for creating an application and includes an example of updating an old application using the new library.
|
||||
|
||||
**Tip**: The authorization system behaves in a uniform way for any version of CARTO.js. You can read about the [fundamentals of authorization]({{site.fundamental_docs}}/authorization/) or know implementation details of the [Auth API]({{site.authapi_docs}}/) under the hood.
|
||||
|
||||
At a high-level, the workflow consists of:
|
||||
|
||||
1. Define the client parameters to manage layers and dataviews:
|
||||
- [`new carto.Client`]({{site.cartojs_docs}}/reference/#cartoclient)
|
||||
- [`addLayers`]({{site.cartojs_docs}}/reference/#cartoclientaddlayer)
|
||||
- [`addDataview`]({{site.cartojs_docs}}/reference/#cartoclientadddataview) or [`addDataviews`]({{site.cartojs_docs}}/reference/#cartoclientadddataviews)
|
||||
- [`getDataviews`]({{site.cartojs_docs}}/reference/#cartoclientgetdataviews)
|
||||
|
||||
2. Define the Base data source objects:
|
||||
- Add dataset as the source [`carto.source.dataset`]({{site.cartojs_docs}}/reference/#cartosourcedataset)
|
||||
- Add SQL to filter data [`carto.source.sql`]({{site.cartojs_docs}}/reference/#cartosourcesql)
|
||||
|
||||
3. Publish the App:
|
||||
- [`getLayers`]({{site.cartojs_docs}}/reference/#cartoclientgetlayers)
|
||||
|
||||
You should understand the following changes in concept before you begin.
|
||||
|
||||
#### Dataset Privacy
|
||||
|
||||
Since we now have a new authorization system for the entire CARTO platform, directly related to dataset privacy, datasets can be public and private as well. Read the [basics of authorization]({{site.fundamental_docs}}/authorization/) to learn more about this aspect of the CARTO platform.
|
||||
|
||||
#### Map Workflow
|
||||
|
||||
`new carto.Client` is the main entry point for building your application. This enables you to communicate between your app and your CARTO account by using your API Key. This enhancement clearly identifies client requests separate from visualization requests.
|
||||
|
||||
#### `createVis`
|
||||
|
||||
The current beta of CARTO.js only includes a JavaScript library, it does not include `creatVis` components to maintain your app. A future enhancement of the library will include functionality for maintaining your core application.
|
||||
|
||||
#### `Dataview`
|
||||
|
||||
A Dataview enables you to create different views of data stored in a table. CARTO.js uses `Dataviews` to add interactive widgets for viewing and filtering map data.
|
||||
|
||||
#### SQL API Integration
|
||||
|
||||
CARTO.js no longer includes a client for the SQL API. Developers looking to get data from their CARTO account can query SQL API with AJAX or the new [JS Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)..
|
||||
|
||||
## Upgrading an Existing Application
|
||||
|
||||
Suppose you have an app that was created with an earlier version of CARTO.js? This guide provides an example of CARTO.js components showing the old code modified with updated code.
|
||||
|
||||
The following example shows the application skeleton using version 3.15 of CARTO.js.
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="initial-scale=1.0" />
|
||||
<meta charset="utf-8" />
|
||||
<!-- include CartoDB.js CSS library -->
|
||||
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.15/themes/css/cartodb.css" />
|
||||
<!-- include CartoDB.js library -->
|
||||
<script src="http://libs.cartocdn.com/cartodb.js/v3/3.15/cartodb.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#map {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<script>
|
||||
const map = L.map('map').setView([30, 0], 3);
|
||||
|
||||
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18
|
||||
}).addTo(map);
|
||||
|
||||
cartodb.createLayer(map, {
|
||||
user_name: 'YOUR_USER_NAME',
|
||||
type: 'cartodb',
|
||||
sublayers: [
|
||||
|
||||
{
|
||||
type: "mapnik",
|
||||
sql: 'select * from populated_places_spf',
|
||||
cartocss: '#populated_places_spf[adm0name = "Spain"]{ marker-fill: #fbb4ae; marker-allow-overlap: true;}#populated_places_spf[adm0name = "Portugal"]{ marker-fill: #ccebc5; marker-allow-overlap: true;}#populated_places_spf[adm0name = "France"]{ marker-fill: #b3cde3; marker-allow-overlap: true;}'
|
||||
}
|
||||
]
|
||||
})
|
||||
.addTo(map);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
In order to make this example work with version 4 of CARTO.js, modify the code as follows:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="initial-scale=1.0" />
|
||||
<meta charset="utf-8" />
|
||||
<!-- Include Leaflet -->
|
||||
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
||||
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
|
||||
<!-- Include CARTO.js -->
|
||||
<script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/%VERSION%/carto.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#map {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<script>
|
||||
const map = L.map('map').setView([30, 0], 3);
|
||||
|
||||
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18
|
||||
}).addTo(map);
|
||||
|
||||
// define client
|
||||
const client = new carto.Client({
|
||||
apiKey: 'YOUR_API_KEY',
|
||||
username: 'YOUR_USER_NAME'
|
||||
});
|
||||
// define source of data => dataset of your account
|
||||
const source = new carto.source.Dataset(`populated_places_spf`);
|
||||
// define CartoCSS code to style data on map
|
||||
const style = new carto.style.CartoCSS(`
|
||||
#layer[adm0name = "Spain"]{
|
||||
marker-fill: #fbb4ae;
|
||||
marker-allow-overlap: true;
|
||||
}
|
||||
#layer[adm0name = "Portugal"]{
|
||||
marker-fill: #ccebc5;
|
||||
marker-allow-overlap: true;
|
||||
}
|
||||
#layer[adm0name = "France"]{
|
||||
marker-fill: #b3cde3;
|
||||
marker-allow-overlap: true;
|
||||
}`);
|
||||
// create CARTO layer from source and style variables
|
||||
const Cartolayer = new carto.layer.Layer(source, style);
|
||||
|
||||
// add CARTO layer to the client
|
||||
client.addLayer(Cartolayer);
|
||||
|
||||
// get tile from client and add them to the map object
|
||||
client.getLeafletLayer().addTo(map);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
#### Conclusion
|
||||
|
||||
For more details about how to use CARTO.js, [view the examples]({{site.cartojs_docs}}/examples/) section for specific features of CARTO.js in action.
|
||||
@@ -0,0 +1,35 @@
|
||||
## Glossary
|
||||
|
||||
This glossary defines terms that appear throughout the CARTO.js documentation.
|
||||
|
||||
### A
|
||||
|
||||
#### Ajax
|
||||
|
||||
Asynchronous JavaScript + XML, while not a technology in itself, is a term coined in 2005 by Jesse James Garrett, that describes a "new" approach to using a number of existing technologies together, including HTML or XHTML, Cascading Style Sheets, JavaScript, The Document Object Model, XML, XSLT, and most importantly the XMLHttpRequest object. More info about Ajax at [Ajax](https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX).
|
||||
|
||||
### C
|
||||
|
||||
#### Client
|
||||
|
||||
Throughout CARTO.js documentation, `client` refers to the object used as an entry point to CARTO.js features.
|
||||
|
||||
It's the object used to add your account credentials and to manage layers and dataviews.
|
||||
|
||||
More info at [carto.Client]({{site.cartojs_docs}}/reference/#cartoclient)
|
||||
|
||||
### L
|
||||
|
||||
#### Layer
|
||||
|
||||
A layer object is used to visualize geospatial data in CARTO.js. They have a source, where the data comes from, and a style, defining how you want the layer to look like.
|
||||
|
||||
They are showed on top of a Leaflet or a Google map.
|
||||
|
||||
[Layer reference]({{site.cartojs_docs}}/reference/#cartolayerlayer)
|
||||
|
||||
### P
|
||||
|
||||
#### Promise
|
||||
|
||||
Promise objects are a standard way for handling asynchronous tasks in Javascript. More info about promises at [Using Promises - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises).
|
||||
@@ -0,0 +1,203 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Guide | CARTO</title>
|
||||
<meta name="viewport" content="initial-scale=1.0">
|
||||
<meta charset="utf-8">
|
||||
<!-- Include Leaflet -->
|
||||
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
||||
<link href="https://unpkg.com/leaflet/dist/leaflet.css" rel="stylesheet">
|
||||
<!-- Include CARTO.js -->
|
||||
<script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/%VERSION%/carto.min.js"></script>
|
||||
<!-- Fonts -->
|
||||
<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>
|
||||
const map = L.map('map').setView([50, 15], 4);
|
||||
|
||||
// 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);
|
||||
|
||||
var client = new carto.Client({
|
||||
apiKey: 'default_public',
|
||||
username: 'cartojs-test'
|
||||
});
|
||||
const europeanCountriesDataset = new carto.source.Dataset(`
|
||||
ne_adm0_europe
|
||||
`);
|
||||
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;
|
||||
}
|
||||
}
|
||||
`);
|
||||
const europeanCountries = new carto.layer.Layer(europeanCountriesDataset, europeanCountriesStyle);
|
||||
|
||||
const populatedPlacesSource = new carto.source.SQL(`
|
||||
SELECT *
|
||||
FROM ne_10m_populated_places_simple
|
||||
WHERE adm0name IN (SELECT admin FROM ne_adm0_europe)
|
||||
`);
|
||||
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;
|
||||
}
|
||||
`);
|
||||
const populatedPlaces = new carto.layer.Layer(populatedPlacesSource, populatedPlacesStyle, {
|
||||
featureOverColumns: ['name']
|
||||
});
|
||||
|
||||
client.addLayers([europeanCountries, populatedPlaces]);
|
||||
|
||||
client.getLeafletLayer().addTo(map);
|
||||
|
||||
|
||||
const popup = L.popup({ closeButton: false });
|
||||
populatedPlaces.on(carto.layer.events.FEATURE_OVER, featureEvent => {
|
||||
popup.setLatLng(featureEvent.latLng);
|
||||
if (!popup.isOpen()) {
|
||||
popup.setContent(featureEvent.data.name);
|
||||
popup.openOn(map);
|
||||
}
|
||||
});
|
||||
|
||||
populatedPlaces.on(carto.layer.events.FEATURE_OUT, featureEvent => {
|
||||
popup.removeFrom(map);
|
||||
});
|
||||
|
||||
const averagePopulation = new carto.dataview.Formula(populatedPlacesSource, 'pop_max', {
|
||||
operation: carto.operation.AVG
|
||||
});
|
||||
|
||||
averagePopulation.on('dataChanged', data => {
|
||||
refreshAveragePopulationWidget(data.result);
|
||||
});
|
||||
|
||||
function refreshAveragePopulationWidget(avgPopulation) {
|
||||
const widgetDom = document.querySelector('#avgPopulationWidget');
|
||||
const averagePopulationDom = widgetDom.querySelector('.js-average-population');
|
||||
averagePopulationDom.innerText = Math.floor(avgPopulation);
|
||||
}
|
||||
|
||||
client.addDataview(averagePopulation);
|
||||
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
function refreshCountriesWidget(adminNames) {
|
||||
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);
|
||||
}
|
||||
|
||||
client.addDataview(countriesDataview);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user