Add support for Allmaps MapLibre plugin
The Allmaps MapLibre plugin seems like it would be a really handy way to work with georeferenced maps. Here is some more background on the plugin and Allmaps project:
Allmaps plugin for MapLibre GL. This plugin allows displaying georeferenced IIIF images on a MapLibre map. The plugin works by loading Georeference Annotations and uses WebGL to transform images from a IIIF image server to overlay them on their correct geographical position. See allmaps.org for more information.
I'm not sure how a plugin should be implemented with mapgl but I saw that the add_h3j_source() function extends another Maplibre plugin so I'm hoping it is possible.
@elipousson I've got a working, 75%-vibe-coded, version here: https://github.com/mhpob/mapgl/tree/allmap. I'm using it as a way to dip a toe into the language, so there's a lot of work before it's ready for anything resembling a PR. Options aren't implemented, doesn't match the style of the rest of the package, etc., but IIIF-referenced maps appear!
If you have any experience at all with this or if you would like a crack at it, I'd appreciate all the help I can get.
@mhpob That is amazing! I will definitely take a look and share code or feedback wherever I can.
It seems this plugin works by adding the layer to the map, then adding the georeferenced map to the layer. (Current docs: https://allmaps.org/docs/packages/maplibre/). I've gotten it to work by placing the following in maplibre.js, which loops through the provided Allmaps URLs, but it feels hacky, so I'm more than happy to take recommendations here:
async function allmaps(map, georef_map){
// Create the warped map layers
let warpedMapLayers = georef_map.map(
item => new Allmaps.WarpedMapLayer(item.id)
);
// Add layer to the map
for (let i = 0; i < georef_map.length; i++) {
map.addLayer(warpedMapLayers[i], georef_map[i].before_id);
await warpedMapLayers[i].addGeoreferenceAnnotationByUrl(georef_map[i].url);
// Set optional properties if provided
...
}
}
map.on("load", function () {
...
if (x.georeferenced_map) {
allmaps(map, x.georeferenced_map);
}
})
where:
const x = {
...,
georeferenced_map: [
{
id: "ID1",
url: 'https://annotations.allmaps.org/images/73def4ccb56259d3'
},
...
]
}
Here is the current additional code: https://github.com/walkerke/mapgl/compare/main...mhpob:mapgl:allmaps-maplibre
@walkerke is this something you'd eventually want as a PR (after Shiny is implemented)? This is specifically a MapLibre plugin, but seems to work with Mapbox GL.
Alternately, it could be shifted to a separate package as a plugin a la leafletextras: https://gist.github.com/jcheng5/c084a59717f18e947a17955007dc5f92
Native js implementation in Observable: https://observablehq.com/d/db081811bd9dd0f9
Current R port: https://github.com/user-attachments/assets/4134d8a4-f6fa-42e4-bb57-fbc0192be588
A plugin package until we get clarity over whether to include this: https://github.com/mhpob/allmaps.
pak::pak("mhpob/allmaps")
library(mapgl)
library(allmaps)
mapgl::maplibre(center = c(-71.04, 42.36), zoom = 11) |>
allmaps::add_allmaps(
id = "ID",
url = 'https://annotations.allmaps.org/images/73def4ccb56259d3'
)
Nice! I think a plugin package makes a ton of sense given that it's reasonably unique.