Skip to main content

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 */
},
});
ParameterValueDescription
type"geojson"Specifies this is a GeoJSON source
dataGeoJSON objectContains 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"];
  • $type is 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 CaseGeometry TypesExample Applications
Park/Reserve MappingPolygon + PointsPark boundary with entrance points
Transport NetworksLineString + PointsRoads with bus stops
Building ComplexesPolygon + PointsBuilding outlines with amenities
Survey DataPoints + PolygonsSample points with area boundaries

Performance Tips

  1. 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
  2. Filter Efficiency

    • Filters are applied during rendering, so all data is still loaded
    • For very large datasets, consider splitting into separate sources
  3. Layer Order

    • Layers are drawn in the order they're added
    • Add point layers last so they appear on top of polygons/lines