I am trying to save a map in html format from a shiny app, however, the map is saved alright but the dimensions from the map displayed on my mainPanel are different than the saved map. I would like to use saveWidget()
instead of mapshot2
because for some unknown reason, the maps created with mapshot2 gives me errors once the shiny app is published. The problem that I am having is that I don't know how to pass the dimensions in tags$head(tags$script
from the mainPanel to saveWidget()
. See example below:
library(shiny)
library(mapview)
library(leaflet)
library(htmlwidgets)
#Ensure webshot is installed and PhantomJS is set up
if (!webshot::is_phantomjs_installed()) {
webshot::install_phantomjs()
}
ui <- fluidPage(
tags$head(tags$script(
'var dimension = [0, 0];
$(document).on("shiny:connected", function(e) {
dimension[0] = document.getElementById("mymap").clientWidth;
dimension[1] = document.getElementById("mymap").clientHeight;
Shiny.onInputChange("dimension", dimension);
});
$(window).resize(function(e) {
dimension[0] = document.getElementById("mymap").clientWidth;
dimension[1] = document.getElementById("mymap").clientHeight;
Shiny.onInputChange("dimension", dimension);
});
')),
sidebarLayout(
sidebarPanel(
downloadButton("print_map", "Download html")),
mainPanel(
leafletOutput("mymap"))
)
)
server <- function(input, output, session) {
output$mymap <- renderLeaflet({
mapview(breweries)@map
})
# Create a new map based off of the user's zoom level
user.created.map <- reactive({
mapview(breweries)@map %>%
setView( lng = input$mymap_center$lng
, lat = input$mymap_center$lat
, zoom = input$mymap_zoom)
})
#THE CODE BELOW WORKS DOWNLOADING THE MAP BUT THE MAP DOESN'T MATCH THE DIMENSIONS OF THE mainPanel
output$print_map <- downloadHandler(
filename = "map_zoom.html",
content = function(file){
saveWidget(widget = user.created.map(), file = file)
#remove_controls = c("zoomControl", "layersControl"),vwidth #input$dimension[1], vheight = input$dimension[2])
}
)
}
shinyApp(ui, server)
mapshot2 takes the following arguments:
mapshot2(user.created.map(),file = file, remove_controls = c("zoomControl", "layersControl"),vwidth = input$dimension[1], vheight = input$dimension[2])
Is there a way to pass the remove_control
along with vwidth
and vheight
to saveWidget()
so the map get the same dimensions as the mainPanel?
(1) Do you want to maintain the aspect ratio of mymap or the literal dimensions? Assuming you mean the dimensions you retrieve from the map using JS, you can use these to set width
and height
of the mapview widget.
(2) Assuming you want to remove zoom- / layer-controls from your map, you can do so using htmlwidgets::onRender
and then setting the styles of the controls to 'none'
.
library(shiny)
library(mapview)
library(leaflet)
library(htmlwidgets)
ui <- fluidPage(
tags$head(
tags$script(
'var dimension = [0, 0];
$(document).on("shiny:connected", function(e) {
dimension[0] = document.getElementById("mymap").clientWidth;
dimension[1] = document.getElementById("mymap").clientHeight;
Shiny.onInputChange("dimension", dimension);
});
$(window).resize(function(e) {
dimension[0] = document.getElementById("mymap").clientWidth;
dimension[1] = document.getElementById("mymap").clientHeight;
Shiny.onInputChange("dimension", dimension);
});
'
)
),
sidebarLayout(
sidebarPanel(
downloadButton("print_map", "Download html")
),
mainPanel(leafletOutput("mymap"))
)
)
server <- \(input, output, session) {
output$mymap <- renderLeaflet(mapview(breweries)@map)
# Create a new map based off of the user's zoom level
user.created.map <- reactive({
mapview(breweries)@map %>%
setView(lng = input$mymap_center$lng, lat = input$mymap_center$lat, zoom = input$mymap_zoom)
})
#THE CODE BELOW WORKS DOWNLOADING THE MAP BUT THE MAP DOESN'T MATCH THE DIMENSIONS OF THE mainPanel
output$print_map <- downloadHandler(
filename = "map_zoom.html",
content = function(file) {
saveWidget(
widget = user.created.map() %>% {
.$width <- input$dimension[1] # set widget-width to current mymap's width
.$height <- input$dimension[2] # set widget-height to current mymap's height
.
} |>
htmlwidgets::onRender( # this hides the layer and zoom controll from the downloaded widget
"
function(el, x) {
document.querySelector('.leaflet-control-layers-toggle').style.display = 'none';
document.querySelector('.leaflet-control-zoom').style.display = 'none';
}
"
),
file = file
)
}
)
}
shinyApp(ui, server)