Bind input$plotBrush and textInput together - r

I would like to bind input$plotBrush to textInput and vice versa so that when I draw my x brush on my plot it set the same boundaries ([brush]$xmin and [brush]$xmax) to the related text input and when I enter my values in my textInput, it draws me a brush on my plot whith the same boundaries entered.
I wasn't able to find any solution on accessing the [brush]$xmin and [brush]$xmax variable
(problem is : updateBrushInput does'nt exist)
Here is a reproductible example :
(the text inputs are set and returns [brush]$xmin and [brush]$xmax from the brushPlot, but the filter only works in one way)
library(shiny)
library(leaflet)
library(leaflet.extras)
library(tidyverse)
library(sf)
#Create T0New data
lat <- c(49.823, 49.823, 58.478, 57.478, 45.823)
lng <- c(-10.854,-10.854,-10.854,2.021,2.02)
date_start_min <- c(123,125,135,168,149)
T0New <- data.frame(lat,lng)
ui <- fluidPage(
leafletOutput("map", height = "50vh"),
textInput("input1","Date start (from 123 to 149)",value = ""),
textInput("input2","Date end (from 123 to 149)",value = ""),
plotOutput("distribPlot", height = "47vh",
brush = brushOpts(id = "distribPlot_brush", direction = "x", resetOnNew = FALSE))
)
server <- function(input, output, session) {
observeEvent(input$distribPlot_brush, {
brush <- input$distribPlot_brush
if (!is.null(brush)) {
updateTextInput(session, "input1", value=brush$xmin)
updateTextInput(session, "input2", value=brush$xmax)
}
})
#filter data from plot sel
filteredGraphData <- reactive({
currentlyFiltered <- T0New
if(!is.null(input$distribPlot_brush)){
thisSel <- input$distribPlot_brush
currentlyFiltered <- currentlyFiltered %>%
filter(date_start_min >= thisSel$xmin, date_start_min <= thisSel$xmax)
}
return(currentlyFiltered)
})
#Output map
output$map <- renderLeaflet({
leaflet()%>%
addProviderTiles(providers$OpenTopoMap)
})
observe({
mapData <- filteredGraphData()
mapProxy <- leafletProxy("map", session = session, data = mapData)
mapProxy %>%
clearGroup('A') %>%
addCircleMarkers(
data = mapData,
lat = mapData$lat,
lng = mapData$lng,
radius = 5,
color = 'red',
stroke = F,
fillOpacity = 1,
group = 'A'
)
})
#outputPlot
output$distribPlot <- renderPlot({
distribPlot <- ggplot(T0New,aes(date_start_min)) +
geom_density(col = "#053144", fill = "#43a2ca", alpha = 0.3, adjust = 0.75)
return(distribPlot)
})
}
# Create Shiny app ----
shinyApp(ui = ui, server = server)

Related

R Shiny with Leaflet - change color of marker after click

I am developing a Shiny app that shows a Leaflet map with markers.
The markers are clickable and I collect the IDs of the clicked markers.
But I also want to change the color of a clicked marker. When the marker is blue it should change to a red marker and vice versa.
So far I have the code to keep track of the clicked markers and I can store the IDs in a table.
output$mymap <- renderLeaflet({
leaflet() %>%
addProviderTiles("OpenStreetMap", group = "OSM",
options = providerTileOptions(minZoom = 4, maxZoom = 20)) %>%
addMarkers(data = points, lng = ~X, lat = ~Y, layerId = ~id, popup = ~paste(id))
})
d <- c()
values <- reactiveValues(df = data.frame(photo_ids=d))
newEntry <- observeEvent(input$mymap_marker_click,{
clicked_id <- input$mymap_marker_click$id
selected_photos <- values$df$photo_ids
if( clicked_id %in% selected_photos ){
selected_photos <- selected_photos[!selected_photos %in% clicked_id]
} else {
selected_photos <- c(selected_photos, clicked_id)
}
#d_new <- c(values$df$photo_ids,as.numeric(clicked_id))
values$df <- data.frame(photo_ids=selected_photos)
updateTextInput(inputId = "selected_photos", value = paste(unlist(values$df), collapse = ",") )
})
But how can I set the style of the marker in the click event?
edit:
Reproducible example (clicked markers are tracked but their style does not change):
library("shiny")
library("sf")
library("leaflet")
library("rgeos")
selected_photos <- c()
getData <- function(){
sf_poly <- "POLYGON ((7.207031 46.97463, 7.182312 46.89868, 7.267456 46.86864, 7.392426 46.85831, 7.529755 46.86864, 7.67807 46.90618, 7.683563 46.97557, 7.592926 47.03082, 7.371826 47.01584, 7.207031 46.97463))"
sf_poly <- st_as_sf(readWKT(sf_poly))
points <- st_as_sf(st_sample(sf_poly, 20))
points$id <- 1:nrow(points)
coords <- st_coordinates(points)
df <- data.frame(st_drop_geometry(points), coords)
return(df)
}
ui <- fluidPage(
titlePanel("Leaflet Map"),
sidebarLayout(
sidebarPanel(
textInput(inputId="selected_photos", label="Selected images", value = "", placeholder = NULL)
),
mainPanel(
leafletOutput("mymap")
)
)
)
server <- function(input, output, session) {
#https://groups.google.com/g/shiny-discuss/c/LWk4ZYNhsSc
points <- getData()
output$mymap <- renderLeaflet({
leaflet() %>%
addProviderTiles("OpenStreetMap", group = "OSM") %>%
addMarkers(data = points, lng = ~X, lat = ~Y, layerId = ~id)
})
d <- c()
values <- reactiveValues(df = data.frame(photo_ids=d))
newEntry <- observeEvent(input$mymap_marker_click,{
clicked_id <- input$mymap_marker_click$id
selected_photos <- values$df$photo_ids
if( clicked_id %in% selected_photos ){
selected_photos <- selected_photos[!selected_photos %in% clicked_id]
} else {
selected_photos <- c(selected_photos, clicked_id)
}
values$df <- data.frame(photo_ids=selected_photos)
updateTextInput(inputId = "selected_photos", session = session, value = paste(unlist(values$df), collapse = ",") )
})
}
shinyApp(ui, server)
We can use addAwesomeMarkers to customize the icon color as suggested in the docs and use leafletProxy to change it on click:
library(shiny)
library(sf)
library(leaflet)
library(geojsonsf)
getData <- function(){
poly <- '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[7.207031249999999,46.97463048970666],[7.18231201171875,46.89867745059795],[7.267456054687499,46.86864162233212],[7.392425537109376,46.85831292242506],[7.529754638671874,46.86864162233212],[7.678070068359375,46.9061837801476],[7.683563232421874,46.97556750833867],[7.592926025390624,47.03082254778662],[7.371826171874999,47.01584377790821],[7.207031249999999,46.97463048970666]]]}}]}'
sf_poly <- geojson_sf(poly)
points <- st_as_sf(st_sample(sf_poly, 20))
points$id <- 1:nrow(points)
coords <- st_coordinates(points)
df <- data.frame(st_drop_geometry(points), coords)
return(df)
}
ui <- fluidPage(
titlePanel("Leaflet Map"),
sidebarLayout(
sidebarPanel(
textInput(inputId="selected_photos", label="Selected images", value = "", placeholder = NULL)
),
mainPanel(
leafletOutput("mymap")
)
)
)
server <- function(input, output, session) {
#https://groups.google.com/g/shiny-discuss/c/LWk4ZYNhsSc
points <- getData()
points$clicked <- FALSE
RV <- reactiveValues(points = points)
icons <- awesomeIcons(
icon = 'ios-close',
iconColor = 'white',
library = 'ion',
markerColor = "blue"
)
output$mymap <- renderLeaflet({
leaflet() %>%
#addTiles() %>%
addProviderTiles("OpenStreetMap", group = "OSM") %>%
addAwesomeMarkers(data = points, lng = ~X, lat = ~Y, layerId = ~id, icon = icons)
})
myLeafletProxy <- leafletProxy(mapId = "mymap", session)
observeEvent(input$mymap_marker_click,{
clicked_point <- input$mymap_marker_click
RV$points[points$id==clicked_point$id,]$clicked <- !(RV$points[points$id==clicked_point$id,]$clicked)
updateTextInput(inputId = "selected_photos", value = paste(unlist(RV$points$id[which(RV$points$clicked)]), collapse = ", "))
removeMarker(map = myLeafletProxy, layerId = clicked_point$id)
addAwesomeMarkers(map = myLeafletProxy,
lng = clicked_point$lng,
lat = clicked_point$lat,
layerId = clicked_point$id,
icon = awesomeIcons(
icon = 'ios-close',
iconColor = 'white',
library = 'ion',
markerColor = ifelse(RV$points[clicked_point$id,]$clicked, yes = "red", no = "blue")
))
})
}
shinyApp(ui, server)

Double calls to plot/load functions in shiny app

I have an app with a map, dropdown, calendar and line plot (my real app is much bigger but I have simplified as much as I can). The problem with it is that when I modify any of the uicontrol features, the data loading and plotting routines run twice (as evidenced from the print statements). In the full app the plots display a reasonable amount of data so running them twice leads to poor performance.
The app is structured so that I can select 1 of 2 predefined points on the map and it will change the dropdown and graph. A new location can also be selected with the dropdown menu (which in turn updates the map). There is also a checkbox to lock the timeframe and when this is not selected the timeframe gets reset to the extents of the timeseries for the new location.
I have isolated the problem to the updateDateRangeInput that is called in the server.R file (line 35). I can comment this out and the problem goes away, but then I lose the functionality to reset the calendar to the new timeframe. Does anyone know how I can keep that functionality but stop the data loading and plotting code from running twice?
Example app below:
app.R
library(shiny)
library(rsconnect)
source('ui.R')
source('server.R')
ui <- ui_page()
server <- server_page(input, output, session)
shinyApp(ui=ui, server=server)
ui.R
library(shiny)
library(leaflet)
library(dygraphs)
inc_level <- 5
ui_page <- function(){
fluidPage(
titlePanel("TEST APP"),
sidebarLayout(
sidebarPanel(
leafletOutput('region_map'),
selectInput(inputId = "Site",label = "Pick a site",choices = c("A","B"), selected = "A"),
fluidRow(
column(6,
dateRangeInput(inputId = "timeframe",label="Select time range", start ="2015-07-01", end = "2016-07-01")),
column(4,checkboxInput(inputId = "lock_timeframe",label = "Lock Time Range"))
)
),
mainPanel(
tabsetPanel(
tabPanel("Plot 1", dygraphOutput(outputId = "plot1"))
)
)
)
)
}
server.R
library(shiny)
library(ggplot2)
library(dygraphs)
library(xts)
server_page <- function(input, output, session){
# Create Data -------------------------------------------------------------
Y1 <- c(21000, 23400, 26800)
Time1 <- startdate <- as.Date(c('2007-11-1','2008-3-25','2010-3-14'))
Y2 <- c(11000, 11400, 16800)
Time2 <- startdate <- as.Date(c('2001-11-1','2003-3-25','2005-3-14'))
Lat <-c(-39.095980, -39.605823)
Lon <- c(173.887903, 173.824561)
Site <- c("A","B")
# Extract Data -------------------------------------------------------
df1 <- reactive({
print("load data")
if (input$Site=="A"){
df1 <- data.frame(Time1, Y1)
}
else if (input$Site=="B"){
df1 <- data.frame(Time2, Y2)
}
names(df1) <- c("Time","Y")
if (1){ # IF YOU CHANGE THIS TO A 0 FUNCTIONLITY IS LOST BUT PROBLEM GOES AWAY
lockTest <- input$lock_timeframe
if (lockTest==FALSE){
updateDateRangeInput(session, "timeframe",
start = df1$Time[1],
end =df1$Time[length(df1$Time)])
}
}
df1 <- df1[df1$Time >= format(input$timeframe[1]) & df1$Time <= format(input$timeframe[2]),]
validate(need(nrow(df1)!=0, "No Data In Range"))
return(df1)
}) #%>% bindCache(input$Site) # I woudl like to cache based on location to stop reloading of data from file in the full app
# Line Plot --------------------------------------------------------
output$plot1 <- renderDygraph({
print("Plotting")
data <- df1()
data <- xts(x = data$Y, order.by = data$Time)
dyPlt <- dygraph(data,width = 800, height = 400)
})
# Plot Map -----------------------------------------------------
output$region_map <- renderLeaflet({
y <- Lat
x <- Lon
id <- Site
leaflet() %>%
addProviderTiles(providers$OpenStreetMap, options = providerTileOptions(noWrap = TRUE)) %>%
setView(lng = 174.051515, lat = -39.301619, zoom = 8) %>%
addCircleMarkers(lng = x, lat = y ,color="green", radius = 2, layerId = id, label = id,
labelOptions = labelOptions(noHide = F, direction = "bottom",
style = list("color" = "green","border-color" = "rgba(0,0,0,0.5)"))
)
})
# Map Click Behaviour -----------------------------------------------------
#When map is clicked: update map and change dropdown value
observeEvent(input$region_map_marker_click, {
event <- input$region_map_marker_click
updateSelectInput(session,
inputId = "Site",
label = "Pick a site",
choices = Site,
selected = event$id)
})
# Update map when a new site is selected from the dropdown
observeEvent(input$Site, {
update_markers()
})
# Function to redraw markers and highlight the selected location
update_markers <- function(){
y <- Lat
x <- Lon
id <- Site
sitInd <- id == input$Site
leafletProxy("region_map") %>% clearMarkers() %>% addCircleMarkers(lng = x, lat = y ,color="green", radius = 2, layerId = id, label = id,
labelOptions = labelOptions(noHide = F, direction = "bottom",
style = list("color" = "green","border-color" = "rgba(0,0,0,0.5)")),
options = list(zIndex = 200)) %>%
addCircleMarkers(lng = x[sitInd], lat = y[sitInd] ,color="blue", radius = 4, layerId = id[sitInd], label = id[sitInd],
labelOptions = labelOptions(noHide = F, direction = "bottom",
style = list("color" = "blue","border-color" = "rgba(0,0,0,0.5)")),
options = list(zIndex = 300) )
}
}

Reactive Shiny Application

I am trying to create an interactive shiny application that displays a leaflet plot based on a user's date and plot type specification. Ideally, I would like the user to specify whether they would like to view a state-wide or a county-wide plot. Then, based on their answers, I would like them to decide whether to use the regular data or the standardized data. After this, they would hit a submit button and the plot would render. I don't want the plot to render until the user presses the "Submit" action button. This is my idea so far, but it fails whenever I try to implement.
library(ggplot2)
library(shapefiles)
library(sp)
library(CARBayes)
library(leaflet)
library(rgdal)
library(leaflet)
library(shiny)
## County Data
dta <- read.csv()
## County Data (percentage)
perc <-read.csv()
## Date Specification Function
selectdates <- function(data, start, end){
keep <- data[, 1:5]
data <- data[, -c(1:5)]
tmp1 <- as.Date(names(data))
tmp2 <- which(tmp1 >= as.Date(start) & tmp1 <= as.Date(end))
tmp <- data[, tmp2]
Sum <- rowSums(tmp)
tmp <- cbind(keep, Sum)
return(tmp)
}
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Mapping"),
tags$em(""),
tags$hr(),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
dateRangeInput("daterange", "Date Range:",
start = as.character(Sys.Date() - 6),
end = as.character(Sys.Date())),
selectInput("ptChoice", "Type of Plot:", choices = c("", "County-Wise", "State-Wise")),
selectInput("typeChoice", "Data Type:", choices = c("", "Raw", "Percentage")),
actionButton("submitButton", "Submit", class = "btn btn-primary")
),
# Display leaflet plot of cases
mainPanel(
leafletOutput("countyPlot"),
leafletOutput("statePlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
observeEvent(input$ptChoice, {
req(input$ptchoice)
if(input$ptChoice == "County-Wide"){
hide("statePlot")
show("countyPlot")
}
else{
hide("countyPlot")
show("statePlot")
}
})
fdta <- eventReactive(input$typeChoice, {
if (input$typeChoice == "Raw"){
df <- selectdates(data = tmp, start = input$daterange[1], end = input$daterange[2])
row.names(df) <- df$FIPS
}else if (input$typeChoice == "Percentage"){
df <- selectdates(data = perc, start = input$daterange[1], end = input$daterange[2])
}else {return(NULL)}
df
})
observeEvent(input$submitButton, {
output$statePlot <- renderLeaflet({
## INSERT STATE PLOT CODE HERE
})
output$countyPlot <- renderLeaflet({
## Loads SHP and DBF File
shp <- read.shp()
dbf <- read.dbf()
sp <- combine.data.shapefile(data = fdta, shp = shp, dbf = dbf)
proj4string(sp) <- CRS("+proj=longlat +datum=WGS84 +no_defs")
sp <- spTransform(sp, CRS("+proj=longlat +datum=WGS84 +no_defs"))
colours <- colorNumeric(palette = "YlOrRd", domain = sp#data$Sum)
leaflet(sp) %>%
addTiles() %>%
addPolygons(
fillColor = ~ colours(Sum),
weight = 1,
opacity = 0.7,
color = "white",
dashArray = '3',
fillOpacity = 0.7,
highlight = highlightOptions(
weight = 5,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE
)
) %>%
addLegend(
pal = colours,
values = sp#data$Sum,
opacity = 1,
title = "Count"
) %>%
addScaleBar(position = "bottomleft")
})
})
}
# Run the application
shinyApp(ui = ui, server = server)
You can put the two plots inside an observeEvent, if you want it only after someone clicks on submit button. To use the appropriate dataframe, create a reactive dataframe and then use it as dfa() to generate the appropriate plot. Try this
server = function(input, output) {
observeEvent(input$ptChoice,{
req(input$ptChoice)
if(input$ptChoice == "County-Wide"){
hide("statePlot")
show("countyPlot")
}else{
hide("countyPlot")
show("statePlot")
}
})
dfa <- eventReactive(input$typechoice, {
if (input$typechoice == "Regular") {
df <- dta
}else if (input$typechoice == "Standardized") {
df <- dta2
}else {return(NULL)}
df
})
observeEvent(input$submitButton,{
output$stateplot <- renderLeaflet({
state <- CODE FOR STATE PLOT
})
output$countyPlot <- renderLeaflet({
county <- CODE FOR COUNTY PLOT
})
})
}
You might want to have your leaflet plot be stored in reactiveValues (rv) - then, you can have one output for your plot, and show what is stored in rv.
To change the plot when the submit button is pressed, be sure to reference the input$submitButton with your observeEvent.
Here is a working example that can be adapted. You could use an additional function to generate the plots based on your input values.
library(ggplot2)
library(leaflet)
library(shiny)
ui = fluidPage(
titlePanel("Leaflet Plot"),
tags$em(""),
tags$hr(),
sidebarLayout(
sidebarPanel(
selectInput("plotChoice", "Type of Plot:", choices = c("", "Boston", "Chicago")),
actionButton("submitButton", "Submit", class = "btn btn-primary")
),
# Display leaflet plot of cases
mainPanel(
leafletOutput("leafletPlot")
)
)
)
server = function(input, output) {
rv <- reactiveValues(plot = NULL)
output$leafletPlot <- renderLeaflet({
rv$plot
})
observeEvent(input$submitButton, {
if (input$plotChoice == "Boston") {
rv$plot <- leaflet() %>% setView(lng = -71.0589, lat = 42.3601, zoom = 12) %>% addTiles()
} else {
rv$plot <- leaflet() %>% setView(lng = -87.6298, lat = 41.8781, zoom = 12) %>% addTiles()
}
})
}
shinyApp(ui = ui, server = server)

Dynamic polygons value with leaflet and shiny

i would like to generate colored polygons, with dynamic values based on option choosen form combo box (specific supplier name).
I used leaflet package to print polygons based on 'SpatialPolygonsDataFrame' object class. And it works fine. I have problems with using 'reactive' shiny function - is change object class from 'SpatialPolygonsDataFrame' to 'data.frame' - creatling leflet map is impossible.
Here is part of my code:
ui <- pageWithSidebar(
sidebarPanel(
# supplier selection
selectInput(inputId = "inpSuppl", label = "supplier:",
choices = sort(x=names(table(db$SUPPLIER)), decreasing=FALSE),
selected = sort(x=names(table(db$SUPPLIER)), decreasing=FALSE)[[1]]
)
),
mainPanel(leafletOutput("myMap"))
)
server <- function(input, output, session) {
myData <- reactive({
data <- data[data$SUPPLIER==input$inpSuppl, c("A_COLUMN")]
})
output$myMap <- renderLeaflet({
m <- leaflet()
m <- addTiles(m)
m <- addPolygons(map = m, data = myData(), stroke = FALSE, fillColor = ~pal(mapval))
})
}
shinyApp(ui=ui, server=server)
Any idea?
Thanks so much. I have another problem - with color palette. i would like to change number of clusters and then color polygons. When i start app everything is all right, but after i change down number of clusters in input field, number of cluster don't work proper (number of cluster don't shrink).
ui <- bootstrapPage(
leafletOutput("myMap", width = "100%", height = "100%"),
absolutePanel(top = 100, left = 10, width = "160px",
# input - supplier
selectInput(inputId = "inpSuppl", label = "supplier:",
choices = sort(x=names(table(db$SUPPLIER)), decreasing=FALSE),
selected = sort(x=names(table(db$SUPPLIER)), decreasing=FALSE)[[1]]
),
# input - variable type
selectInput(inputId = "inpVar", label = "variable:", choices = c("turnover" = "VAL_1", "basket" = "VAL_2")),
# numeric input - number of clusters
numericInput(inputId="inpClust", label="number of clusters:", value=3, step=1)
)
)
# --------------------------------------------------------------------------
server <- function(input, output, session) {
# dynamic number of clusters
clusters <- reactive({input$inpClust})
# dynamic data set - adding specific variable from db object to sh2 object
ld <- reactive({
# add aditional data to sh2 object (SpatialPolygonsDataFrame class)
# from db obejct (data.frame class)
sh2$mapval <- db[db$SUPPLIER==input$inpSuppl, c(input$inpVar)]
# create clusters
k <- kmeans(sh2$mapval, clusters())
# add clusters to sh2 object (SpatialPolygonsDataFrame class)
sh2$cluster <- k$cluster
return(sh2)
})
# create color pal
colorpal <- reactive({colorNumeric(palette="YlOrRd", ld()$cluster)})
# static map elements
output$myMap <- renderLeaflet({
m <- leaflet("myMap") # preapare leaflet object
m <- addTiles(m)
m <- addPolygons(m, data = sh0, color = "black", weight = 1, fillColor = "black") # country polygon
})
# dynamic map elements
observe({
pal <- colorpal()
leafletProxy("myMap", data = ld()) %>%
addPolygons(stroke = FALSE, fillColor = ~pal(cluster), fillOpacity=0.6, popup = ~paste(mapval)) # powiats polygons
})
}
ui <- pageWithSidebar(
sidebarPanel(
# supplier selection
selectInput(inputId = "inpSuppl", label = "supplier:",
choices = sort(x=names(table(db$SUPPLIER)), decreasing=FALSE),
selected = sort(x=names(table(db$SUPPLIER)), decreasing=FALSE)[[1]]
)
),
mainPanel(leafletOutput("myMap"))
)
server <- function(input, output, session) {
myData <- reactive({
data <- data[data$SUPPLIER==input$inpSuppl, c("A_COLUMN")]
data
})
output$myMap <- renderLeaflet({
m <- leaflet()
m <- addTiles(m)
m <- addPolygons(map = m, data = myData(), stroke = FALSE, fillColor = ~pal(mapval))
})
}
shinyApp(ui=ui, server=server)
Per the comments above.

Select or highlight data on map by click on legend

Is there any way to select or highlight data on a leaflet map in by clicking on the legend in Rshiny?
example code:
library(shiny)
library(leaflet)
library(RColorBrewer)
library(leafletGeocoderRshiny)
ui <- fluidPage(
leafletOutput("map"),
p(),
actionButton("recalc", "New points")
)
server <- function(input, output, session) {
df = data.frame(x = rnorm(100), y = rexp(100, 2), z = runif(100))
pal = colorBin('PuOr', df$z, bins = c(0, .1, .4, .9, 1))
output$map <- renderLeaflet({ leaflet(df) %>%
addCircleMarkers(~x, ~y, color = ~pal(z)) %>%
addLegend(pal = pal, values = ~z)
})
}
shinyApp(ui, server)
The recent updates (0.2) to the mapedit package may help: http://r-spatial.org/r/2017/06/09/mapedit_0-2-0.html
I got close, but ran out of time now. But i decided to share anyway, maybe someone else sees a solution to the last step.
So far it works for the first click on any of the rectangles in the legend. It doesnt work for any following clicks as the map is redrawn and with it the onclick listeners are deleted. I didnt find a way to add them again so far,...
Its a hacky aprroach: I add onclick listener to the boxes and decided to update the colors via R as i didnt see a good way in JS.
library(shiny)
library(leaflet)
library(RColorBrewer)
library(leafletGeocoderRshiny)
library(shinyjs)
colors <- c("#000000", "#222222", "#888888", "#FFFFFF")
ui <- fluidPage(
useShinyjs(),
leafletOutput("map"),
p(),
actionButton("recalc", "New points")
)
server <- function(input, output, session) {
global <- reactiveValues(colors = colors,
bins = c(0, .1, .4, .9, 1))
observe({
print(input$interval)
isolate({
if(!is.null(input$interval)){
lowerBound <- as.numeric(unlist(input$interval))
global$colors <- colors
global$colors[which(global$bins == lowerBound)] <- "#FF0000"
}
})
})
session$onFlushed(function() {
runjs("
var legendButton = document.getElementsByTagName('i')
var elem; var interval;
for (nr = 0; nr < legendButton.length; nr++) {
elem = legendButton[nr]
elem.onclick = function(e){
console.log(e.target)
interval = e.target.nextSibling.nodeValue.split(' ');
Shiny.onInputChange('interval', interval[1]);
}
}
")
})
df = data.frame(x = rnorm(100), y = rexp(100, 2), z = runif(100))
pal = reactive({
colorBin(global$colors, df$z, bins = global$bins)
})
output$map <- renderLeaflet({ leaflet(df) %>%
addCircleMarkers(~x, ~y, color = ~pal()(z)) %>%
addLegend(pal = pal(), values = ~z)
})
}
runApp(shinyApp(ui, server), launch.browser = T)

Resources