mapgl icon indicating copy to clipboard operation
mapgl copied to clipboard

Add support for Allmaps MapLibre plugin

Open elipousson opened this issue 9 months ago • 6 comments

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 avatar Mar 21 '25 04:03 elipousson

@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 avatar Oct 22 '25 20:10 mhpob

@mhpob That is amazing! I will definitely take a look and share code or feedback wherever I can.

elipousson avatar Oct 22 '25 23:10 elipousson

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

mhpob avatar Oct 27 '25 20:10 mhpob

Native js implementation in Observable: https://observablehq.com/d/db081811bd9dd0f9

Current R port: https://github.com/user-attachments/assets/4134d8a4-f6fa-42e4-bb57-fbc0192be588

mhpob avatar Oct 27 '25 20:10 mhpob

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'
  )

mhpob avatar Nov 04 '25 20:11 mhpob

Nice! I think a plugin package makes a ton of sense given that it's reasonably unique.

walkerke avatar Nov 04 '25 22:11 walkerke