Public
Edited
Jan 18, 2024
1 star
Insert cell
Insert cell
Insert cell
Insert cell
viewof map = {
let container = html`<div style='height:600px;' />`;

// Give the container dimensions.
yield container;

// set the targomo client
const client = tgmCoreClient("westcentraleurope");

// Create the "map" object with the mapboxgl.Map constructor, referencing
// the container div
const mapRef = (container.value = new maplibre.Map({
container,
center: source,
zoom: 11,
pitch: 40,
style: client.basemaps.getGLStyleURL("Light"),
// scrollZoom: false,
attributionControl: false
})
.addControl(new maplibre.NavigationControl())
.addControl(
new maplibre.AttributionControl({
compact: true,
customAttribution: attribution
})
));

mapRef.on("mouseenter", "hexes", function () {
mapRef.getCanvas().style.cursor = "pointer";
});

// Change it back to a pointer when it leaves.
mapRef.on("mouseleave", "hexes", function () {
mapRef.getCanvas().style.cursor = "";
});

mapRef.on("click", "hexes", function (e) {
var { lng, lat } = e.lngLat;
const time = e.features[0].properties.value;
const html = `<strong>${e.features[0].properties.pointid}</strong><br>${time} seconds`;
new maplibre.Popup().setLngLat({ lng, lat }).setHTML(html).addTo(mapRef);
});

await new Promise((resolve, reject) => {
mapRef.on("load", async () => {
mapRef.addSource("hexes", {
type: "geojson",
data: turf.featureCollection([])
});

mapRef.addLayer(
{
id: "hexes",
type: "fill",
source: "hexes",
filter: ["<=", "value", 1800],
layout: {},
paint: {
"fill-color": ["get", "color"],
"fill-opacity": 0.65,
"fill-outline-color": "rgba(0, 0, 0, 0)"
}
},
"place_other"
);
resolve();
});
});

invalidation.then(() => mapRef.remove());
yield container;
}
Insert cell
viewof mapMarker = {
const inp = Inputs.input({ id: "src", ...source });
const marker = new maplibre.Marker({
draggable: true
})
.setLngLat(source)
.addTo(map);

marker.on("dragend", () => {
inp.value = { id: "src", ...marker.getLngLat() };
inp.dispatchEvent(new Event("input", { bubbles: true }));
});
return inp;
}
Insert cell
{
map.getSource("hexes").setData(data);
}
Insert cell
{
clipToMax
? map.setFilter("hexes", ["<=", ["get", "value"], 1800])
: map.setFilter("hexes");
}
Insert cell
Insert cell
viewof buffer = Inputs.range([0, 1000], {
label: "Buffer (m)",
value: 0,
step: 200
})
Insert cell
viewof hexSize = Inputs.select([6, 7, 8, 9, 10, 11], {
label: html`<strong>H3 resolution</strong>`,
value: 9
})
Insert cell
viewof travelMode = Inputs.radio(
[
{ label: "Walk", value: "walk" },
{ label: "Bike", value: "bike" },
{ label: "Car", value: "car" },
{ label: "Transit", value: "transit" }
],
{
label: html`<strong>Select mode of transport</strong>`,
value: "transit",
format: (d) => d.label,
valueof: (d) => d.value
}
)
Insert cell
Insert cell
data = {
// here we're deciding that we want transit coverage, 30 minutes (1800s), nodes (as we are aggregating with deckGL)
const multigraphOptions = {
edgeWeight: "time",
maxEdgeWeight: 1800,
multigraph: {
layer: {
type: "h3hexagon",
geometryDetailLevel: hexSize
},
serialization: {
format: "json",
h3MaxBuffer: buffer
}
},
sources: [{ id: 1, ...mapMarker, ...{ tm: { [travelMode]: {} } } }]
};

// set the targomo client
const client = tgmCoreClient("westcentraleurope");
const mg = await fetch(
`https://api.targomo.com/westcentraleurope/v1/multigraph?key=${targomoKey()}`,
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(multigraphOptions)
}
).then((response) => response.json());

const coverage = Object.keys(mg.data);
return geojson2h3.h3SetToFeatureCollection(coverage, (d) => ({
pointid: d,
value: mg.data[d].w,
color: tgmColorInterpolator(1800)(mg.data[d].w)
}));
}
Insert cell
html`
<style>
.panel {
display: grid;
grid-template-columns: repeat(2,auto);
column-gap: 20px;
row-gap: 20px;
}
</style>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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