I am trying to use leaflet to show a smaller map than usual so I don't want to use the normal tiling system. I don't care about smooth zooming and loading higher resolution tiles when needed. Instead I am trying to add a raster image from an image file. Lets say this file that comes up when I google "hand drawn map"
So I try
download.file('https://external-preview.redd.it/7tYT__KHEh8FBKO6bsqPgC02OgLCHAFVPyjdVZI4bms.jpg?auto=webp&s=ff2fa2e448bb92c4ed6c049133f80370f306acb3',
destfile = 'map.jpg')
map = raster::raster('map.jpg')
# it seems like i need a projection to use a raster image.
# not sure what controls do I have over this, especially in
# absence of a proper map layer and it's likely
# part of the solution
crs(map) = CRS("+init=epsg:4326")
leaflet() %>%
leaflet::addRasterImage(map)
The resulting output is nothing like the input image
How do I take an arbitrary image and place in on a leaflet map?
I failed to find the exact reason why addRasterImage
fails here but I found reports that it doesn't behave well on L.CRS.Simple
projection, which is what you'll want to use to show a simple rectangle image.
Using htmlwidgets::onRender
makes it possible to directly use the javascript function L.imageOverlay
to add the image you want
library(leaflet)
# minimal custom image
imageURL = 'https://external-preview.redd.it/7tYT__KHEh8FBKO6bsqPgC02OgLCHAFVPyjdVZI4bms.jpg?auto=webp&s=ff2fa2e448bb92c4ed6c049133f80370f306acb3'
# get image data. we'll use this to set the image size
imageData =
magick::image_read(imageURL) %>% image_info()
leaflet(options = leafletOptions(crs = leafletCRS('L.CRS.Simple'))) %>%
htmlwidgets::onRender(glue::glue("
function(el, x) {
var myMap = this;
var imageUrl = '<imageURL>';
var imageBounds = [[<-imageData$height/2>,<-imageData$width/2>], [<imageData$height/2>,<imageData$width/2>]];
L.imageOverlay(imageUrl, imageBounds).addTo(myMap);
}
",.open = '<', .close = '>'))
For a large image like this if you want to make the image smaller you can either scale down using the imageBounds
in javascript side or set minZoom
to a negative value and use setView
to start out zoomed out.
leaflet(options =
leafletOptions(crs = leafletCRS('L.CRS.Simple'),
minZoom = -1)) %>%
setView(0,0,zoom = -1) %>%
htmlwidgets::onRender(glue::glue("
function(el, x) {
var myMap = this;
var imageUrl = '<imageURL>';
var imageBounds = [[<-imageData$height/2>,<-imageData$width/2>], [<imageData$height/2>,<imageData$width/2>]];
L.imageOverlay(imageUrl, imageBounds).addTo(myMap);
}
",.open = '<', .close = '>'))