GeoJSON data and styles
Slide 1: What is GeoJSON?
GeoJSON is a lightweight, widely used data format for representing geographic objects in a web environment. It is based on the JSON (JavaScript Object Notation) format, a lightweight, easy-to-read and easy-to-write text data format widely supported by many libraries and development tools, including Leaflet, OpenLayers, and other GIS (Geographic Information Systems) systems.
GeoJSON is specifically designed to describe geographic objects, such as points, lines, polygons, and sets of these objects, while including additional information (such as attributes) about these objects. It is used to integrate and exchange geospatial data in modern web applications and GIS systems.
Slide 2: Structure of a GeoJSON file
A GeoJSON file is a textual data format based on the JSON standard, designed to represent geographic objects. It is commonly used in web mapping applications. The objects contained in a GeoJSON file are organized according to a hierarchical structure, centered around three key elements:
1. FeatureCollection
This is the root element (the main container) of a GeoJSON file. It groups together a set of features, i.e. individual geographic entities. A FeatureCollection can contain different types of geographic objects: points, lines or polygons. As a general rule, a GeoJSON file contains a single FeatureCollection.
2. Feature
Each geographic entity is defined as a feature. A feature represents a specific object on the map (such as a building, a tree, a path, a protected area, etc.). It is made up of two essential parts:
- geometry: this is the geometric description of the object, which can take the form of a Point, LineString or Polygon. Geometry is defined by type and coordinates.
- properties: this is descriptive information associated with the object (metadata). They can include a name, a category, a description, a date, a numerical value, etc. These properties are expressed in the form of key-value pairs, as in an object identity card.
3. Geometry
Geometry specifies the shape and spatial position of a feature. It is based on a type and one or more geographic coordinates (longitude, latitude). The most commonly used geometry types are :
- Point: a single location on the map, defined by a pair of coordinates [longitude, latitude].
- LineString: a line made up of several interconnected points.
- Polygon: a set of points forming a closed surface (e.g. parcel, lake, municipality).
- MultiPoint, MultiLineString, MultiPolygon: these types can be used to group together several similar geometries in a single feature (e.g. an archipelago, a road network, a set of protected areas).
Slide 3: Why use GeoJSON?
Advantages of GeoJSON
Easy to read and write: Being JSON-based, the format is easy to understand and manipulate.
Compatibility: It is widely supported by modern JavaScript libraries (such as Leaflet, OpenLayers, Mapbox), as well as by many GIS tools.
Lightweight format: GeoJSON is a lightweight, text-based format that lends itself well to web use, especially for geospatial data transfer.
Extensibility: GeoJSON lets you add custom properties to geographic objects, making it flexible for a variety of applications.
Limitations of GeoJSON
Performance: Although GeoJSON is lightweight, data size can increase considerably when working with large quantities of complex geographic objects.
Lack of support for multiple projections: GeoJSON works primarily with the EPSG:4326 (latitude/longitude) projection, which can be problematic for certain applications requiring specific projections.
Slide 4: Loading a GeoJSON file
Loading an external GeoJSON file into Leaflet is simple and efficient, whether via a direct URL or an HTTP request like fetch(). This functionality is essential for integrating real-time geospatial data from external servers, which is very common in web mapping applications
Slide 5: With fetch()
When working with Leaflet to display interactive maps, you can load a local GeoJSON file directly into your JavaScript code. This file can be included in the same folder as your application, so you can use it without having to make an external HTTP request. This is particularly useful for local data or when you want to pre-load geographic objects onto the map.
For example, here’s a GeoJSON file describing a point representing a location:
Let’s assume that this file is saved under the name paris.geojson in the same folder as your HTML file. If you have an external GeoJSON file in the same directory as your application (e.g. paris.geojson), you can use fetch() to retrieve the file and add it to the map. Here’s an example:
With this code (L.geoJSON(data).addTo(map)) the GeoJSON point is indeed added to the map, but it is not visible because no style or popup is defined, and a Point without a custom icon or popup is not displayed by default in Leaflet. Here’s a corrected version of the HTML code with a popup and default icon that makes the “Paris” point visible: fetch(‘paris.geojson’) .then(response => response.json()) .then(data => { L.geoJSON(data, { pointToLayer: function (feature, latlng) { return L.marker(latlng).bindPopup( “<b>” + feature.properties.name + “</b><br>” + feature.properties.description ); } }).addTo(map); }) .catch(error => console.error(‘Erreur lors du chargement du fichier GeoJSON :’, error)); If you prefer not to use an external file and include the GeoJSON data directly in the JavaScript code, you can define the GeoJSON object in a variable and add it directly to the map. Example: <!DOCTYPE html> </html> Code explanation: In this example, the GeoJSON is defined directly in a JavaScript variable (geojsonData). This approach is simple and suitable when you have relatively small GeoJSON data and don’t want to make external requests to load it. Advantages: Easy to implement, especially for simple GeoJSON files or projects with small amounts of data. No need to handle complex HTTP requests. Limitations: The fetch() method requires the file to be served via a local or remote server (no direct access to local files via the browser without a server). If you have a lot of geospatial data, direct loading via JavaScript can become cumbersome and less efficient. Conclusion Loading a local GeoJSON file into Leaflet is a simple operation that can be performed in two main ways: either by using the fetch() method to load an external file, or by including the GeoJSON data directly in your JavaScript code. This flexibility makes it easy to integrate geographic objects into interactive maps. Conditional styling in Leaflet lets you customize the appearance of geographic elements (points, lines, polygons) according to their properties or other criteria. This makes maps more interactive and informative, displaying different colors, sizes or shapes according to specific values. For example, polygons can be colored according to their surface area, or markers of varying size can be displayed according to a city’s population. In Leaflet, you can apply conditional styles based on the properties of a GeoJSON object. This is usually done in the style function, which is passed to the L.geoJSON() method. This function allows you to define a customized style for each feature based on its properties. Geospatial objects in Leaflet, such as points, polylines, polygons or GeoJSON layers, can be styled by defining parameters such as color, line thickness, fill, etc. Here’s a detailed example of how to customize a style. When working with GeoJSON objects, you can customize their style using a style function. This function supports parameters such as line color, polygon fill, opacity and more. Here’s an example of how to customize the style of GeoJSON objects: <!DOCTYPE html> Explanation: color: Defines the polygon’s border color. weight: Defines the border’s thickness. fillColor: Defines the polygon’s fill color. fillOpacity: Defines the polygon’s fill opacity. opacity: Defines the border’s opacity. When working with GeoJSON data, you can also customize popups according to the properties of geographic objects. Here’s how to do it: <!DOCTYPE html> </html> Explanation: onEachFeature: This function is called for each GeoJSON object. It is used to customize interactions, including popups. bindPopup(): Here, popup content is defined dynamically from GeoJSON properties. Conclusion Customizing styles and popups in Leaflet makes it possible to create more interactive and visually appealing maps. You can style geospatial objects such as polygons and polylines, and add interactive popups to provide additional information. Whether for a simple interactive map or a more complex application, customizing styles and popups plays a key role in making the user experience more enjoyable and functional. When working with GeoJSON data, it is often useful to change the appearance of a polygon according to its properties. This allows you, for example, to quickly visualize differences in altitude, density, surface area, etc. Here’s an example where polygons are colored according to altitude: function polygonStyle(feature) { fillColor: feature.properties.altitude > 300 ? “green” : “yellow”, // Altitude > 300m = vert, sinon jaune weight: 2, // Épaisseur des contours opacity: 1, // Opacité du contour (1 = totalement opaque) color: “black”, // Couleur du contour dashArray: “3”, // Trait en pointillés fillOpacity: 0.5 // Opacité du remplissage (0.5 = semi-transparent) }; } Et voici comment l’utiliser lors de l’ajout d’un calque GeoJSON : style: polygonStyle }).addTo(map); Step-by-step explanation feature.properties.altitude: retrieves the altitude property of each polygon. fillColor: condition ? “green” : “yellow” : a ternary condition is used: If the altitude is greater than 300, the fill color will be green. Otherwise, it will be yellow. This logic makes the map visually informative: you can immediately distinguish high areas (green) from low areas (yellow), without having to read the data. Customization possible
Add a tooltip or popup to display details on hover or click. The aim here is to make the map interactive: display information, react to user clicks, or even modify the appearance of an element in real time. When using L.geoJSON(…), you can specify a special option called onEachFeature. What does onEachFeature do? This function is called automatically for each “feature” in the GeoJSON file. It allows you to:{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.3522, 48.8566]
},
"properties": {
"name": "Paris",
"description": "La capitale de la France"
}
}
]
}
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Carte Leaflet avec GeoJSON local</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
</head>
<body>
<div id="map" style="height: 600px;"></div>
<script>
// Initialiser la carte
var map = L.map('map').setView([48.8566, 2.3522], 13); // Vue sur Paris
// Ajouter une couche de base (carte OpenStreetMap)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
// Charger le fichier GeoJSON local et l'ajouter à la carte
fetch('paris.geojson')
.then(response => response.json()) // Convertir la réponse en JSON
.then(data => {
// Ajouter l'objet GeoJSON à la carte
L.geoJSON(data).addTo(map);
})
.catch(error => console.error('Erreur lors du chargement du fichier GeoJSON :', error));
</script>
</body>
</html>
Code explanation:
// Charger le fichier GeoJSON
View the HTML page in a new tab.
Slide 6: Insert directly into the code
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Carte Leaflet avec GeoJSON local</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
</head>
<body>
<div id="map" style="height: 600px;"></div>
<script>
// Initialiser la carte
var map = L.map('map').setView([48.8566, 2.3522], 13); // Vue sur Paris
// Ajouter une couche de base (carte OpenStreetMap)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
// Définir les données GeoJSON directement dans une variable
var geojsonData = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.3522, 48.8566]
},
"properties": {
"name": "Paris",
"description": "La capitale de la France"
}
}
]
};
// Ajouter l'objet GeoJSON à la carte
L.geoJSON(geojsonData).addTo(map);
</script>
</body>
View HTML page in new tab.
Advantages and limitations
Slide 7: Conditional styling with Leaflet
Customizing styles for geospatial objects
Customizing styles with GeoJSON
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Carte Leaflet avec GeoJSON personnalisé</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
</head>
<body>
<div id="map" style="height: 600px;"></div>
<script>
// Initialiser la carte
var map = L.map('map').setView([48.8566, 2.3522], 13); // Vue sur Paris
// Ajouter une couche de base (carte OpenStreetMap)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
// Données GeoJSON (ici un simple polygone)
var geojsonData = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[2.35, 48.85],
[2.36, 48.85],
[2.36, 48.86],
[2.35, 48.86],
[2.35, 48.85]
]
]
},
"properties": {
"name": "Paris Square"
}
}
]
};
// Fonction pour personnaliser le style du polygone
var style = function (feature) {
return {
color: "blue", // Couleur de la bordure
weight: 3, // Épaisseur de la bordure
opacity: 1, // Opacité de la bordure
fillColor: "lightblue", // Couleur de remplissage
fillOpacity: 0.5 // Opacité du remplissage
};
};
// Ajouter les données GeoJSON avec le style personnalisé
L.geoJSON(geojsonData, { style: style }).addTo(map);
</script>
</body>
</html>
View HTML page in new tab.
Slide 8 : Other available style properties
Customizing a GeoJSON popup
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Carte Leaflet avec Popups et GeoJSON</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
</head>
<body>
<div id="map" style="height: 600px;"></div>
<script>
// Initialiser la carte
var map = L.map('map').setView([48.8566, 2.3522], 13); // Vue sur Paris
// Ajouter une couche de base (carte OpenStreetMap)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
// Données GeoJSON avec des propriétés pour chaque objet
var geojsonData = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.3522, 48.8566]
},
"properties": {
"name": "Paris",
"description": "La capitale de la France"
}
}
]
};
// Ajouter les données GeoJSON à la carte avec un popup personnalisé
L.geoJSON(geojsonData, {
onEachFeature: function (feature, layer) {
layer.bindPopup("<b>" + feature.properties.name + "</b><br>" + feature.properties.description);
}
}).addTo(map);
</script>
</body>
Slide 9: Conditional styling of a polygon
Applying dynamic styles to polygons with Leaflet
// Fonction de style pour les polygones, basée sur l'altitude
return {
L.geoJSON(geojsonPolygons, {
Slide 10 : Interacting with GeoJSON in Leaflet
Interacting with GeoJSON objects in Leaflet
The onEachFeature option
L.geoJSON(data, {
onEachFeature: function(feature, layer) {
// Action à réaliser pour chaque entité GeoJSON
}
});
Simple example: popup with the name
L.geoJSON(data, {
onEachFeature: function(feature, layer) {
// Affiche le nom dans une popup
layer.bindPopup(feature.properties.nom);
}
}).addTo(map);
When the user clicks on an entity (point, line or polygon), a popup box opens with the value of the “name” property.
This function can be enhanced by adding several types of interaction:
onEachFeature: function(feature, layer) {
layer.bindPopup("<b>" + feature.properties.nom + "</b>");
// Changer la couleur au survol
layer.on("mouseover", function () {
this.setStyle({ color: "blue" });
});
// Remettre la couleur d'origine à la sortie de la souris
layer.on("mouseout", function () {
this.setStyle({ color: "black" });
});
}
In short,
onEachFeature is the ideal gateway to interactive maps. This function defines the behavior of each GeoJSON entity displayed on the map.
Exercise session 3: Displaying and interacting with GeoJSON data in Leaflet
Objective:
Create an interactive map displaying areas dynamically styled according to their attributes, with a popup on click.
Content:
You will work with a small HTML file containing :
- A Leaflet map centered on Mauritius
- GeoJSON polygons representing fictitious zones (agricultural and urban)
- Conditional styling according to zone type
- A popup displaying information about each zone
This file is …\leaflet_starter_kit\data\exercice_geojson.html
View this file in a new tab.
To do:
- Open the HTML file in a browser (you can save it locally as exercise-geojson.html).
- Observe:
- The map displays two polygons, each colored according to its type.
- When clicked, a popup appears with the zone name and type.
- Understand:
- The style is defined by the styleFeature() function, which tests feature.properties.type.
- Interaction is defined by onEachFeature, which binds a bindPopup() to each entity.
- Modify the code to perform the following exercises:
- Add a new “forest” zone with simple geometry.In styleFeature(),
- give the “forest” zone a different color (e.g. ‘darkgreen’).
- In onEachFeature(), modify the popup content so that it also displays a small message like “Click to zoom”.
- Add a click event (layer.on(‘click’, …)) that automatically zooms in on the clicked area (map.fitBounds(layer.getBounds())).
Bonus:
- Add a different opacity depending on the type of zone.
- Test a mouseover and mouseout effect.
Expected result:
A map with three colored zones, each with :
- Own style
- Custom popup
- Click interaction