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
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)
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)
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()
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.
I am trying to create an interactive webmap in R to display locations using Shiny and Leaflet
The idea is that the user selects one input and the markers corresponding to that input(lat/long which are to be fetched from data set of the corresponding input) are displayed in a Leaflet map (with zoom in/out function).
Any help/advice would be greatly appreciated!
(sample data file uploaded here):
enter code here
Server.R
library(shiny)
library(rpart.plot)
library(leaflet)
shinyServer(
function(input, output) {
output$dtmplot <- renderPlot({
dtmplot <- rpart.plot(dtm, type=4, extra=101)
})
observe({
output$map <- renderLeaflet( {
for(j in 1:nrow(df))
{
if(df[j, "col1"]==input$input1) {
map <- leaflet() %>%
addTiles() %>%
addMarkers(lng=df[j,"Longitude"], lat=df[j,"Latitude)
}
}
})
})
}
)
enter code here
UI.R
library(shiny)
library(leaflet)
shinyUI(
pageWithSidebar(
headerPanel("Sample project"),
sidebarPanel(
plotOutput("dtmplot"),
selectInput("input1",
label = "label1:",
choices = c(“choice1”,”choice2”),
selected = " choice1"),
sliderInput("slider","Please select slider input", min=1,max=100,value=20,step=10)
),
mainPanel(
leafletOutput("map")
)
))
The basic code to handle custom points in a leaflet map is available below. The code utilises the official example available on the leaflet GitHub and provided end-user with the functionality to display custom location on the map.
app.R
library(shiny)
library(leaflet)
r_colors <- rgb(t(col2rgb(colors()) / 255))
names(r_colors) <- colors()
ui <- fluidPage(
leafletOutput("mymap"),
p(),
h1("Added example to add more points here:"),
p(),
numericInput("long", label = h3("Longitude:"), value = 11.242828),
numericInput("lat", label = h3("Latitude:"), value = 30.51470),
actionButton("recalc", "Show point")
)
server <- function(input, output, session) {
points <- eventReactive(input$recalc, {
cbind(input$long, input$lat)
}, ignoreNULL = FALSE)
output$mymap <- renderLeaflet({
leaflet() %>%
setView(lat = 30, lng = 11, zoom = 4) %>%
addProviderTiles("Stamen.TonerLite",
options = providerTileOptions(noWrap = TRUE)
) %>%
addMarkers(data = points())
})
}
shinyApp(ui, server)
Results
The obtained map looks like that:
Explanation
The mechanics is fairly simple and can be summarised in the following steps:
You need to pas lat and lon to your map to addMarkers. In my example this is done via primitive input files but it can be done in a number of ways.
You have to decide on the logic of dynamically adding markers to your map; in the presented case this is done with use of an actionButton.
Side notes
As at the time of drafting this answer there was no clarity with respect to the actual data that should be represented on the map, I found it more informative to generate the desired functionality following the official example instead of trying to modify the provided code.
The thing worth noting is that the lat/lon values have to be of correct format to appear on the map.
The map setView to make the example more presentable but in an actual solution, default lat/lon values should be generated dynamically.