dreamRs / apexcharter

:bar_chart: R Htmlwidget for ApexCharts.js
https://dreamrs.github.io/apexcharter
Other
138 stars 15 forks source link

No shared tooltip #62

Closed thisissarah closed 1 year ago

thisissarah commented 1 year ago

Hi, I've plotted a line with an area range which worked fine but I'm having problems with the tooltip. My plot at the moment looks like this: https://i.stack.imgur.com/1DAV0.png But I want the tooltip to look something like this: https://i.stack.imgur.com/euOpv.png In my code I've stated that shared = TRUE but the tooltips are still separate.

This is my example data and code:

test_data <- data.frame(seq(as.POSIXct('2022/09/04 22:00:00'), as.POSIXct('2022/09/08 10:00:00'), by="hour"))
test_data$MIN <- runif(n = 85, min = 70, max = 100)
test_data$MEDIAN <- runif(n = 85, min = 100, max = 120)
test_data$MAX <- runif(n = 85, min = 120, max = 150)
colnames(test_data) <- c("Date", "MIN", "MEDIAN", "MAX")

axc_plot <- apex(data = test_data, # plot the area range
                 mapping = aes(x = test_data[20:60,]$Date, 
                               ymin = test_data[20:60,]$MIN, 
                               ymax = rev(test_data[20:60,]$MAX)), 
                 type = "rangeArea", 
                 serie_name = "Vertrauensbereich") %>% 
  add_line(mapping = aes(x = Date, y = MEDIAN), # add the line
           type = "line", 
           serie_name = "Median") %>% 
  ax_colors("lightblue", "red") %>% # why is the line not red?
  ax_theme(mode = "dark") %>%
  ax_labs(x = "Zeit [h]", 
          y = "Q [m³/s]") %>%
  ax_tooltip(enabled = T, 
             shared = T) # I want it shared but it's not

axc_plot

I can imagine that it's a problem with the format of the tooltips (because they have different titles?) but I don't know how to change that. If you're interested, I also wrote a StackOverflow entry about the formatting problem here: https://stackoverflow.com/questions/74488634/r-apexcharter-formatting-tooltip I would be happy for any help.

pvictor commented 1 year ago

Hello,

Yes the area range tooltip use a custom template, I don't think you mix the both. A solution to achieve the desired look is to create a custom tooltip in HTML in the data then retrieve the value in the actual tooltip. Here's an example :

library(htmltools)

test_data <- data.frame(seq(as.POSIXct('2022/09/04 22:00:00'), as.POSIXct('2022/09/08 10:00:00'), by="hour"))
test_data$MIN <- runif(n = 85, min = 70, max = 100)
test_data$MEDIAN <- runif(n = 85, min = 100, max = 120)
test_data$MAX <- runif(n = 85, min = 120, max = 150)
colnames(test_data) <- c("Date", "MIN", "MEDIAN", "MAX")

# explicit NA if not used in area range
test_data$MIN[-c(20:60)] <- NA
test_data$MAX[-c(20:60)] <- NA

# Construct tooltip with HTML tags
test_data$tooltip <- unlist(lapply(
  X = seq_len(nrow(test_data)),
  FUN = function(i) {
    d <- test_data[i, ]
    doRenderTags(tags$div(
      style = css(padding = "5px 10px;", border = "1px solid #FFF", borderRadius = "5px"),
      format(d$Date, format = "%Y/%m/%d %H:%M"),
      tags$br(),
      tags$span("Q Median:", tags$b(round(d$MEDIAN), "m\u00b3/s")),
      if (!is.na(d$MIN)) {
        tagList(
          tags$br(),
          tags$span("Vertrauensbereich:", tags$b(round(d$MIN), "m\u00b3/s -", round(d$MAX), "m\u00b3/s"))
        )
      }
    ))
  }
))

axc_plot <- apex(
  data = test_data[20:60, ], # plot the area range
  mapping = aes(
    x = Date, 
    ymin = MIN, 
    ymax = rev(MAX),
    tooltip = tooltip # variable containing the HTML tooltip
  ), 
  type = "rangeArea", 
  serie_name = "Vertrauensbereich"
) %>% 
  add_line(
    data = test_data,
    mapping = aes(x = Date, y = MEDIAN, tooltip = tooltip), # use same tooltip variable
    type = "line", 
    serie_name = "Median"
  ) %>% 
  ax_colors(c("lightblue", "#FF0000")) %>% # use HEX code instaed of name
  ax_theme(mode = "dark") %>%
  ax_labs(
    x = "Zeit [h]", 
    y = "Q [m³/s]"
  ) %>% 
  ax_tooltip(
    # Custom tooltip: retrieve the HTML tooltip defined in data
    custom = JS(
      "function({series, seriesIndex, dataPointIndex, w}) {",
      "var tooltip = w.config.series[seriesIndex].data[dataPointIndex].tooltip;",
      "return typeof tooltip == 'undefined' ? null : tooltip;",
      "}"
    )
  )

axc_plot

Let me know if it helps you or if you have further questions.

Victor

thisissarah commented 1 year ago

Thank you very much, this helped a lot! I haven't worked with html tags before so this was very new but I understood what you did except one line: "return typeof tooltip == 'undefined' ? null : tooltip;", I understand we want to return the value of tooltip here but what does 'undefined' ? null mean/do?

pvictor commented 1 year ago

That's a ifelse statement in short mode, it checks if the tooltip is defined , if it exists for the serie in the mapping. If for exemple you remove the aes(..., tooltip = tooltip) in add_line there'll be an error without that line. In R, it'll be something like :

if (!exists("tooltip")) {
  return(NULL)
} else {
  return(tooltip )
}
thisissarah commented 1 year ago

Ah, alright thanks so much for your help!