Multiple GeoJSON Layers
Add and style multiple geometry types (points, lines, polygons) from a single GeoJSON source with independent layer controls.
Complete Working Example
<!DOCTYPE html>
<html lang="en">
<head>
<title>Multiple GeoJSON Geometries - Barikoi Maps</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Barikoi GL CSS -->
<link
rel="stylesheet"
href="https://unpkg.com/bkoi-gl@latest/dist/style/bkoi-gl.css"
/>
<!-- Barikoi GL JS -->
<script src="https://unpkg.com/bkoi-gl@latest/dist/iife/bkoi-gl.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
html,
body,
#map {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
// Initialize the map
const map = new bkoigl.Map({
container: "map",
style: "https://map.barikoi.com/styles/barikoi-light/style.json",
center: [90.378556, 23.762295], // Bangladesh coordinates
zoom: 10,
accessToken: "YOUR_BARIKOI_API_KEY", // ← Replace with your API key
});
// Wait for map to load before adding GeoJSON layers
map.on("load", () => {
// Add GeoJSON source containing multiple geometry types
map.addSource("national-park", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [
// Polygon feature (park boundary)
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[90.34729, 23.80635],
[90.42614, 23.80635],
[90.42614, 23.73456],
[90.4022, 23.70109],
[90.34729, 23.70109],
[90.31403, 23.7279],
[90.34729, 23.80635],
],
],
},
},
// Point features (park entrances/points of interest)
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [90.399452, 23.780573],
},
},
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [90.4022, 23.70109],
},
},
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [90.31403, 23.7279],
},
},
],
},
});
// Add polygon layer (park boundary)
map.addLayer({
id: "park-boundary",
type: "fill",
source: "national-park",
paint: {
"fill-color": "#4CAF50", // Green color
"fill-opacity": 0.3,
"fill-outline-color": "#2E7D32",
},
filter: ["==", "$type", "Polygon"], // Only show Polygon features
});
// Add circle layer (points of interest)
map.addLayer({
id: "park-points",
type: "circle",
source: "national-park",
paint: {
"circle-radius": 8,
"circle-color": "#FF5722",
"circle-stroke-width": 2,
"circle-stroke-color": "#FFFFFF",
},
filter: ["==", "$type", "Point"], // Only show Point features
});
});
</script>
</body>
</html>
How It Works
1. GeoJSON Source Structure
The example uses a FeatureCollection containing multiple features with different geometry types:
{
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: { type: "Polygon", coordinates: [...] } // Park boundary
},
{
type: "Feature",
geometry: { type: "Point", coordinates: [...] } // Entrance 1
},
{
type: "Feature",
geometry: { type: "Point", coordinates: [...] } // Entrance 2
}
]
}
2. Adding the GeoJSON Source
map.addSource("national-park", {
type: "geojson",
data: {
/* GeoJSON data here */
},
});
| Parameter | Value | Description |
|---|---|---|
type | "geojson" | Specifies this is a GeoJSON source |
data | GeoJSON object | Contains all features (polygons, points, lines) |
3. Creating Separate Layers with Filters
Each layer uses a filter to display only specific geometry types:
Polygon Layer (Park Boundary):
filter: ["==", "$type", "Polygon"];
$typeis a special expression that checks the geometry type- Only shows features where geometry type equals "Polygon"
Circle Layer (Points of Interest):
filter: ["==", "$type", "Point"];
- Only shows features where geometry type equals "Point"
Layer Configuration Details
Polygon Fill Layer
{
id: "park-boundary",
type: "fill",
source: "national-park",
paint: {
"fill-color": "#4CAF50", // Solid fill color
"fill-opacity": 0.3, // 30% opacity (semi-transparent)
"fill-outline-color": "#2E7D32" // Border color
},
filter: ["==", "$type", "Polygon"]
}
Circle Layer (Points)
{
id: "park-points",
type: "circle",
source: "national-park",
paint: {
"circle-radius": 8, // Size of the circle
"circle-color": "#FF5722", // Fill color
"circle-stroke-width": 2, // Border thickness
"circle-stroke-color": "#FFFFFF" // Border color
},
filter: ["==", "$type", "Point"]
}
Advanced Examples
Add LineString Features (Trails/Roads)
// Add line features to your GeoJSON
{
type: "Feature",
geometry: {
type: "LineString",
coordinates: [
[90.399452, 23.780573],
[90.4022, 23.70109],
[90.31403, 23.7279]
]
}
}
// Create a line layer
map.addLayer({
id: "park-trails",
type: "line",
source: "national-park",
paint: {
"line-color": "#2196F3",
"line-width": 3,
"line-dasharray": [2, 2] // Dashed line
},
filter: ["==", "$type", "LineString"]
});
Add Properties for Dynamic Styling
{
type: "Feature",
geometry: { type: "Point", coordinates: [...] },
properties: {
"name": "Main Entrance",
"type": "entrance",
"status": "open"
}
}
// Style based on properties
map.addLayer({
id: "smart-points",
type: "circle",
source: "national-park",
paint: {
"circle-color": [
"case",
["==", ["get", "status"], "open"], "#4CAF50",
["==", ["get", "status"], "closed"], "#F44336",
"#9E9E9E" // default color
],
"circle-radius": [
"case",
["==", ["get", "type"], "entrance"], 10,
["==", ["get", "type"], "viewpoint"], 8,
6 // default size
]
}
});
Common Use Cases
| Use Case | Geometry Types | Example Applications |
|---|---|---|
| Park/Reserve Mapping | Polygon + Points | Park boundary with entrance points |
| Transport Networks | LineString + Points | Roads with bus stops |
| Building Complexes | Polygon + Points | Building outlines with amenities |
| Survey Data | Points + Polygons | Sample points with area boundaries |
Performance Tips
Single Source vs Multiple Sources
- ✅ Use single source when features are related (same dataset)
- ✅ Use multiple sources when data comes from different APIs or updates independently
Filter Efficiency
- Filters are applied during rendering, so all data is still loaded
- For very large datasets, consider splitting into separate sources
Layer Order
- Layers are drawn in the order they're added
- Add point layers last so they appear on top of polygons/lines