I would like to add a logo to a leaflet map in a shiny app.
The addLogo function of the leafem package allows this, when I generate a map outside the shiny environment the function works perfectly, however, when applying the function in shiny it does not work.
I do not know what I can be obviating or if there is another way to do it.
├── app.R
└── www
└── Logo.png
library(leaflet)
library(shiny)
library(leafem)
ui <- fluidPage(
leafletOutput("map")
)
server <- function(input, output, session) {
output$map <- renderLeaflet({
leaflet() %>%
addTiles() %>%
setView(lng = -79.442471,
lat = 43.6857,
zoom = 12) %>%
addLogo("Logo.png",
src= "local")
})
}
shinyApp(ui, server)
Use src= "remote" in addLogo. Even though the Shiny app and image is in your local computer, you need to use it as remote. Using local will point to ../graphs/Logo.png instead of only Logo.png (that is the default for files under the www directory).
library(leaflet)
library(shiny)
library(leafem)
ui <- fluidPage(
leafletOutput("map")
)
server <- function(input, output, session) {
output$map <- renderLeaflet({
leaflet() %>%
addTiles() %>%
setView(lng = -79.442471,
lat = 43.6857,
zoom = 12) %>%
addLogo("Logo.png",
src= "remote")
})
}
shinyApp(ui, server)
Related
I'm currently using addSearchOSM() from the leaflet.extras package to search addresses:
How can I change the colour of the circle marker? Will accept CSS solutions as well - I attempted to manually update the .leaflet-interactive{} css, but that changes all interactive elements, including polygons.
Reproducible example here:
library(shiny)
library(leaflet)
library(tidyverse)
library(leaflet.extras)
ui <- fluidPage(
fluidRow(
column(
width = 12,
leafletOutput("map")
)
)
)
server <- function(input, output) {
output$map <- renderLeaflet({
leaflet() %>%
addTiles() %>%
setView(
lng = -73.9888,
lat = 40.72905,
zoom = 12
) %>%
addSearchOSM()
})
}
# Run the application
shinyApp(ui = ui, server = server)
This is the first time I try to reorganize a shiny app into shiny modules, so, some help would be welcome.
My goal is to create a clickable map module with leaflet that would store the latitude and longitude in an input that I could re-use in other modules. Currently the module works by creating in the ui a leafletOutput (id="mymap") and using in the server function a observeEvent function that reacts to click on the map. The click event generates an input vector of the longitude and latitude (input$input$mymap_click$lat[1] & input$mymap_click$lng[1])which is used to place a marker on the map. But I struggle to extract those to values to use it externally by other modules or render* functions. (it works without the "module method" but the code is a bit messy)
For the sake of clarity in my example I try to use the latitude and longitude in a textOutput with renderText instead of in a module.
# clickable leaflet module ----------------------------------------------------------
## loads leaflet library
library(leaflet)
##ui function
clicMapOutput <- function(id) {
ns <- NS(id)
tagList(leafletOutput(ns("mymap")),
textOutput(ns("text")))
}
## serverfunction
clicMapServer <- function(id) {
moduleServer(id,
function(input, output, session) {
# outputs a map
output$mymap <-
leaflet::renderLeaflet({
leaflet() %>% addTiles() %>% setView(lat = 0,
lng = 0,
zoom = 2)
})
# makes map clickable to obtain a marker and a longitude + latitude vector
observeEvent(input$mymap_click, {
output$mymap <-
leaflet::renderLeaflet({
leaflet() %>% addTiles() %>% addMarkers(lat = input$mymap_click$lat[1],
lng = input$mymap_click$lng[1])
})
})
})
}
# Calling modules ---------------------------------------------------------
library(shiny)
ui<-fluidPage(
clicMapOutput("map"),
textOutput("lng")
)
server<-function(input,output,session){
clicMapServer("map")
output$lng<-renderText({
input$mymap_click$lng[1]
})
}
shinyApp(ui=ui,server=server)
the ususal way of doing this is to define a return value in the server part of the module and then using it in the module consumer
## module server
clicMapServer <- function(id) {
moduleServer(id, function(input, output, session) {
## ...
return(reactive(input$mymap_click$lng[1])))
}
}
## consumer server
server <- function(input, output, session) {
lng <- clicMapServer("map")
output$lng <- renderText({ lng() })
}
You should always make sure to wrap the return values with reactives and use the return value like a function. If you want to return more than one variable, see my answer to this question for details.
library(leaflet)
library(shiny)
## module ui
clicMapOutput <- function(id) {
ns <- NS(id)
leafletOutput(ns("mymap"))
}
## module server
clicMapServer <- function(id) {
moduleServer(id, function(input, output, session) {
output$mymap <- renderLeaflet({
leaflet() %>% addTiles() %>% setView(
lat = 0, lng = 0, zoom = 2)
})
# handle click events
observeEvent(input$mymap_click, {
output$mymap <- renderLeaflet({
leaflet() %>% addTiles() %>% addMarkers(
lat = input$mymap_click$lat[1],
lng = input$mymap_click$lng[1])
})
})
return(reactive(input$mymap_click$lng[1]))
})
}
# main ui
ui <- fluidPage(
clicMapOutput("map"),
textOutput("lng")
)
# main server
server <- function(input, output, session) {
lng <- clicMapServer("map")
output$lng <- renderText({ lng() })
}
shinyApp(ui = ui, server = server)
Another thing I noticed is that you are updating the leaflet widget by overwriting output$mymap. It would be better to use leaflet::leafletProxy() instead. Generally speaking, outputs should not be assigned inside observe() or observeEvent()
I am very new to shiny and the mapping function.
Based on the code of the link bellow, I did a simple one, which does not work.
Can someone tell me why is not working?
There is no error shown. However, it doesn't show the map.
I am working with the dataset of NYC bikes.
library(shiny)
library(leaflet)
bikes <- read.csv("Data/201501-citibike-tripdata.csv")
ui <- fluidPage(
leafletOutput("mymap")
)
server <- function(input, output) {
output$mymap <- renderLeaflet({
leaflet(bikes) %>%
setView(lng = -73.98928, lat = 40.75042, zoom = 10) #NYC
})
}
shinyApp(ui=ui, server = server)
link: http://rstudio-pubs-static.s3.amazonaws.com/133599_c0d5471268584d47b53298f0ad27e8d3.html
Leaflet provides an option, when setting up your map, to hide the zoom controls
leaflet(options = leafletOptions(zoomControl = FALSE)
However, I would like to call this option after having already created a map so that a user can download the map without the zoom controls and without me having to re-create a different version of the map from scratch.
Here's a simple version of my app at the moment:
library(shiny)
library(tidyverse)
library(leaflet)
library(mapview)
ui <- fluidPage(
fluidPage(
leafletOutput(outputId = "map"),
downloadButton(outputId = "save")
)
)
server <- function(input, output, session) {
map <- reactive({
leaflet() %>%
addTiles()
})
output$map <- renderLeaflet({
map()
})
output$save <- downloadHandler(
filename = "map.jpeg",
content = function(file){
latRng <- range(input$map_bounds$north,
input$map_bounds$south)
lngRng <- range(input$map_bounds$east,
input$map_bounds$west)
map() %>%
setView(lng = (lngRng[1] + lngRng[2])/2,
lat = (latRng[1] + latRng[1])/2,
zoom = input$map_zoom) %>%
### HERE ###
mapshot(file = file)
}
)
}
shinyApp(ui, server)
I'd like to be able to add a line of code where I've commented ### HERE ### that would turn off zoom controls. In my actual code the displayed map is really complex with lots of options and I wouldn't want to have all that code twice just for the sake of removing zoom controls in the initial call to leaflet().
Thanks
You can do it like so:
library(shiny)
library(tidyverse)
library(leaflet)
library(mapview)
ui <- fluidPage(
fluidPage(
leafletOutput(outputId = "map"),
downloadButton(outputId = "save")
)
)
server <- function(input, output, session) {
map <- reactive({
leaflet() %>%
addTiles()
})
output$map <- renderLeaflet({
map()
})
output$save <- downloadHandler(
filename = "map.jpeg",
content = function(file){
latRng <- range(input$map_bounds$north,
input$map_bounds$south)
lngRng <- range(input$map_bounds$east,
input$map_bounds$west)
m = map() %>%
setView(lng = (lngRng[1] + lngRng[2])/2,
lat = (latRng[1] + latRng[1])/2,
zoom = input$map_zoom)
m$x$options = append(m$x$options, list("zoomControl" = FALSE))
mapshot(m, file = file)
}
)
}
shinyApp(ui, server)
which is updating the leaflet options after map creation. I will incorporate this in the mapshot function to optionally remove the zoomControl.
The following code produces a shiny app with (almost) the same output twice. One uses package "rcharts", the other package "leaflet"
The first map has a fullsreen button. Is this available with package leaflet()?
library(shiny)
library(rCharts)
library(leaflet)
runApp(
## UI ####
list(ui = (basicPage(
headerPanel("tests"),
mainPanel(
chartOutput("map1", "leaflet"),
"some text...",
leafletOutput('map2')
)
)),
## server ####
server = function(input, output) {
output$map1 <- renderMap({
map1 <- Leaflet$new()
map1$fullScreen(TRUE)
map1$setView(c(39.603609, -8.415081), 10)
map1
})
output$map2 <- renderLeaflet({
leaflet() %>%
addTiles() %>%
setView(lng = -8.415081, lat = 39.603609, zoom = 10)
})
}
))
Thanks
For future readers
With the package leaflet.extras you can add a full screen control to your map.
library(leaflet)
library(leaflet.extras)
leaflet() %>%
addTiles() %>%
addFullscreenControl()
There is a plugin for the Leaflet javascript library called Leaflet.Control.FullScreen.
However, this plugin hasn't (yet) been implemented in the R version of leaflet. I have posted a feature request on the leaflet Github page, but haven't heard anything back so far.