Public
Edited
May 16
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
require("maplibre-gl@1.15.2/dist/maplibre-gl.js")

Insert cell
Insert cell
html`<button onclick="document.getElementById('map').querySelector('canvas').toBlob(b => {
const a = document.createElement('a');
a.href = URL.createObjectURL(b);
a.download = 'northeast_bc_map.png';
a.click();
})">Download Map as PNG</button>`

Insert cell
html`<link href="https://unpkg.com/maplibre-gl@1.15.2/dist/maplibre-gl.css" rel="stylesheet" />`

Insert cell
{
const container = mapContainer;
container.innerHTML = "";

const map = new maplibregl.Map({
container: container,
style: "https://api.maptiler.com/maps/basic/style.json?key=bjxk0DGvRqm9M5JfUV88",
center: [-120.85, 56.25],
zoom: 6.5
});

map.on("load", async () => {
const nrrm_all = await FileAttachment("ABMS_MUNICIPALITIES_SP.geojson").json();
const prrd_all = await FileAttachment("ABMS_REGIONAL_DISTRICTS_SP.geojson").json();
const data = await FileAttachment("northeast_bc_map.geojson").json();

// ✅ Combine all NRRM features by name
const nrrm_features = nrrm_all.features.filter(f =>
f.properties?.MUNI_NAME === "Northern Rockies"
);

// ✅ Find PRRD by partial string match
const prrd_feature = prrd_all.features.find(f =>
Object.values(f.properties).some(v =>
typeof v === "string" && v.toLowerCase().includes("peace river")
)
);

// --- PRRD (green base)
map.addSource("prrd", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [prrd_feature]
}
});

map.addLayer({
id: "prrd_fill",
type: "fill",
source: "prrd",
paint: {
"fill-color": "#d9f2d9",
"fill-opacity": 0.5
}
});

// --- NRRM (blue + black outline)
map.addSource("nrrm", {
type: "geojson",
data: {
type: "FeatureCollection",
features: nrrm_features
}
});

map.addLayer({
id: "nrrm_fill",
type: "fill",
source: "nrrm",
paint: {
"fill-color": "#cfe8f3",
"fill-opacity": 0.8
}
});

map.addLayer({
id: "nrrm_border",
type: "line",
source: "nrrm",
paint: {
"line-color": "#333333",
"line-width": 2
}
});

// --- Points
map.addSource("northeast_bc", { type: "geojson", data });

map.addLayer({
id: "northeast_bc_points",
type: "circle",
source: "northeast_bc",
paint: {
"circle-radius": 6,
"circle-color": [
"match",
["get", "category"],
"Geographic Feature", "#1f77b4",
"Municipality", "#ff7f0e",
"First Nation", "#d62728",
"Hydro Infrastructure", "#9467bd",
"Cultural Site", "#8c564b",
"Wilderness Area", "#2ca02c",
"Ecological Site", "#17becf",
"Industrial Site", "#7f7f7f",
"Other", "#d3d3d3",
"#000000"
],
"circle-stroke-width": 1.5,
"circle-stroke-color": "#ffffff"
}
});

// --- Labels (at zoom 9+)
map.addLayer({
id: "northeast_bc_labels",
type: "symbol",
source: "northeast_bc",
minzoom: 9,
layout: {
"text-field": ["get", "name"],
"text-font": ["Open Sans Regular"],
"text-size": 11,
"text-offset": [0, 1.2],
"text-anchor": "top"
},
paint: {
"text-color": "#000000",
"text-halo-color": "#ffffff",
"text-halo-width": 1
}
});

// --- Legend
const legend = document.createElement("div");
legend.style.position = "absolute";
legend.style.bottom = "20px";
legend.style.left = "20px";
legend.style.background = "rgba(255, 255, 255, 0.95)";
legend.style.padding = "10px";
legend.style.fontSize = "12px";
legend.style.fontFamily = "sans-serif";
legend.style.border = "1px solid #ccc";
legend.style.borderRadius = "4px";

legend.innerHTML = `
<strong>Legend</strong><br>
<div><span style="background:#cfe8f3" class="legend-dot"></span> NRRM Boundary</div>
<div><span style="background:#d9f2d9" class="legend-dot"></span> PRRD Boundary</div>
<hr style="margin: 6px 0">
<div><span style="background:#1f77b4" class="legend-dot"></span> Geographic Feature</div>
<div><span style="background:#ff7f0e" class="legend-dot"></span> Municipality</div>
<div><span style="background:#d62728" class="legend-dot"></span> First Nation</div>
<div><span style="background:#9467bd" class="legend-dot"></span> Hydro Infrastructure</div>
<div><span style="background:#8c564b" class="legend-dot"></span> Cultural Site</div>
<div><span style="background:#2ca02c" class="legend-dot"></span> Wilderness Area</div>
<div><span style="background:#17becf" class="legend-dot"></span> Ecological Site</div>
<div><span style="background:#7f7f7f" class="legend-dot"></span> Industrial Site</div>
<div><span style="background:#d3d3d3" class="legend-dot"></span> Other</div>
`;

const styleTag = document.createElement("style");
styleTag.innerHTML = `
.legend-dot {
display: inline-block;
width: 12px;
height: 12px;
margin-right: 6px;
vertical-align: middle;
border: 1px solid #ccc;
border-radius: 2px;
}
`;
document.head.appendChild(styleTag);

container.appendChild(legend);
});

return container;
}

Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more