2

I am using leaflet-heat.js plugin for leaflet. The only way that I could make it work, was through the rCharts library. R shiny leaflet javascript addons - heatmap

The heatmap displays correctly, but I cannot change the heatmap options. In addition, if I uncomment the reactive part of the code, the app crashes.

It seems that the only way to modify the heatmap layer opacity is through CSS, but I cannot figure out how to implement it here. control the opacity of heatmap using leaflet heatmap

Here is the part of the code that works, with the offending lines commented out.

library(shiny)
library(shinydashboard)
library(rCharts)

# Define UI for app

header1 <- dashboardHeader(
  title = "My Dashboard"
)

sidebar1 <- dashboardSidebar(
  sidebarMenu(
    fileInput("file0", "Choose CSV File",
              multiple = TRUE,
              accept = c("text/csv",
                         "text/comma-separated-values,text/plain",".csv")),
    sliderInput("opacity", "Opacity:",
                min = 0, max = 1,
                value = 0.5, step = 0.05),
    sliderInput("radius", "Radius:",
                min = 0, max = 50,
                value = 25),
    sliderInput("blur", "Blur:",
                min = 0, max = 1,
                value = 0.75, step = 0.05),
    sliderInput("maxvalue", "MaxValue:",
                min = 0, max = 1,
                value = 1, step = 0.05)
  ) #sidebarMenu
) #dashboardSidebar

body1 <- dashboardBody(
  fluidRow(
    box(
      title = "Box Title 1", width = 11, solidHeader = TRUE, status = "primary",
      chartOutput("baseMap", "leaflet"),
      tags$style('.leaflet {width: 600px; height: 400px;}'),
      tags$head(tags$script(src="http://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js")),
      uiOutput('heatMap')
    ) #box
  ) #fluidRow
) #dashboardBody

ui <- dashboardPage(header1, sidebar1, body1)

# Define data
dat <- data.frame(latitude = c(14.61),
                  longitude = c(-90.54),
                  intensity = c(100))

# Define SERVER logic
server <- function(input, output, session) {

  opacityoption <- reactive({
    paste("minOpacity = ",as.character(input$opacity))
  })

  radiusoption <- reactive({
    paste("radius = ",as.character(input$radius))
  })

  bluroption <- reactive({
    paste("blur = ",as.character(input$blur))
  })

  maxoption <- reactive({
    paste("max = ",as.character(input$maxvalue))
  })

  output$baseMap <- renderMap({
    baseMap <- Leaflet$new() 
    baseMap$setView(c(14.61,-90.54) ,12) 
    baseMap$tileLayer(provider="Esri.WorldTopoMap")
    baseMap
  })

  output$heatMap <- renderUI({

    j <- paste0("[",dat[,"latitude"], ",", dat[,"longitude"], ",", dat[,"intensity"], "]", collapse=",")
    j <- paste0("[",j,"]")
    j

    tags$body(tags$script(HTML(sprintf("
                                       var addressPoints = %s
                                       var heat = L.heatLayer(addressPoints).addTo(map)"
                                       , j)
    )))

    # THESE LINES DO NOT WORK - THE OBSERVE BLOCK CRASHES
    # tags$body(tags$script(HTML(sprintf("heat.setOptions(minOpacity = 0.5)"
    # )))) #tags$body

    # tags$body(tags$script(HTML(sprintf("heat.setOptions(radius = 50)"
    # )))) #tags$body

    # observe({
    #   tags$body(tags$script(HTML(sprintf(paste("heat.setOptions(",opacityoption,", ",radiusoption,", ",bluroption,", ",maxoption,")")
    #   )))) #tags$body
    # }) #observe

  }) #renderUI

} #server


# Run app
shinyApp(ui, server)

Your help on this will be greatly appreciated! :)

MLavoie
  • 9,671
  • 41
  • 36
  • 56
fhaidacher
  • 123
  • 9
  • if you are interested in heatmap, have you seen this: https://www.rdocumentation.org/packages/leaflet.extras/versions/0.2/topics/addHeatmap – MLavoie Jan 10 '18 at 15:47
  • Thank you for your suggestion! I tried it out with leaflet.extras library, but the heatmap part crashes. Here is my code. Some lines are commented, because they crash the app. – fhaidacher Jan 10 '18 at 23:38
  • Please see the question edit ... – fhaidacher Jan 10 '18 at 23:40
  • The app now works with leaflet in shiny. But whenever I try to do this inside the server block, it crashes. # THESE BLOCK IS COMMENTED OUT BECAUSE IT CRASHES # addHeatmap("MapPlot1", lng = -90.54, lat = 14.61, intensity = 1, # minOpacity = 0.05, max = 1, # radius = 25, blur = 15, # data = leaflet::getMapData(map)) – fhaidacher Jan 10 '18 at 23:49
  • I also need to know how to update the heatmap options ... observeEvent(input$opacity, { # HOW DO I UPDATE THE HEATMAP OPTIONS HERE INSIDE OBSERVE EVENT? }) #observeEvent – fhaidacher Jan 10 '18 at 23:50
  • Library leaflet.extras seems to add functionality to leaflet through third party plugins. This means that plugins like leaflet-heat.js can be used inside Shiny instead of what I am doing here with rCharts. Can you give me just one example of the syntax needed to make it work? – fhaidacher Jan 10 '18 at 23:58

1 Answers1

2

Are you looking for something like this? Here is an example with addHeatmap. Just move your sliderInput and you will see the map will change accordingly. It seems to be not working for the maxvalue, but change the numbers in your sliderInput and it will work. You may want to look also in leafletProxy.

library(shiny)
library(shinydashboard)
library(leaflet)
library(leaflet.extras)

# Define UI for app

header1 <- dashboardHeader(
  title = "My Dashboard"
)

sidebar1 <- dashboardSidebar(
  sidebarMenu(
    fileInput("file0", "Choose CSV File",
              multiple = TRUE,
              accept = c("text/csv",
                         "text/comma-separated-values,text/plain",".csv")),
    sliderInput("opacity", "Opacity:",
                min = 0, max = 1,
                value = 0.5, step = 0.05),
    sliderInput("radius", "Radius:",
                min = 0, max = 50,
                value = 25),
    sliderInput("blur", "Blur:",
                min = 0, max = 30,
                value = 0.75, step = 2),
    sliderInput("maxvalue", "MaxValue:",
                min = 0, max = 1,
                value = 1, step = 0.05)
  ) #sidebarMenu
) #dashboardSidebar

body1 <- dashboardBody(
  fluidRow(
    box(
      title = "Box Title 1", width = 11, solidHeader = TRUE, status = "primary",
      leafletOutput("baseMap"),
      tags$style('.leaflet {width: 600px; height: 400px;}'),
      tags$head(tags$script(src="http://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js"))
    ) #box
  ) #fluidRow
) #dashboardBody

ui <- dashboardPage(header1, sidebar1, body1)

# Define data
dat <- data.frame(latitude = c(14.61, 15),
                  longitude = c(-90.54, -90.65),
                  intensity = c(100, 125))

# Define SERVER logic
server <- function(input, output, session) {

  output$baseMap <- renderLeaflet({
    leaflet(data = dat) %>% addProviderTiles(providers$Stamen.TonerLite,
                                   options = providerTileOptions(noWrap = TRUE)) %>% setView(-90.54, 14.61, zoom = 12) %>%
      addHeatmap(lng = ~longitude, lat = ~latitude, intensity = ~as.numeric(intensity), minOpacity= ~input$opacity, blur = ~input$blur, max = ~input$maxvalue, radius = ~input$radius)
  })


} #server


# Run app
shinyApp(ui, server)
MLavoie
  • 9,671
  • 41
  • 36
  • 56
  • Awesome! This gets in the right direction! However, blur and maxvalue have a problem, because they seem to jump from 0 to infinity when their values are greater than zero. Is there no solution to opacity? I would love to make it work like this ... http://heatmap.joyofdata.de/ – fhaidacher Jan 11 '18 at 15:56
  • see update, you can use minOpacity; Have you tried with a bigger dataset? – MLavoie Jan 11 '18 at 16:06
  • Hi MLavoie! My lower and upper bounds for the parameters were wrong. Your example now works! However, the minOpacity parameter behaves differently than initially expected - it seems to do the opposite of the maxvalue parameter. Is there a way to control the overall opacity of the heatmap layer? – fhaidacher Jan 11 '18 at 16:38
  • Try opacity in the tile options argument – MLavoie Jan 11 '18 at 19:08
  • minOpacity parameter works in a weird way when you have only a few points. After adding more points, minOpacity works as expected. – fhaidacher Jan 12 '18 at 20:49