dreamRs / apexcharter

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

Custom Text in Tooltips #4

Open OGuggenbuehl opened 4 years ago

OGuggenbuehl commented 4 years ago

Hi, I have added tooltips to my chart and although they look very nice, I'd like them to display more information than the current default. At the moment they simply show the x- & y-values of each observation. Is there a way of including more variables in the display than that? I have a character column in my dataframe which I'd like to include in the tooltip, but so far the only further customization option I found is recreating the entire tooltip with HTML.

Thank you again for this package, it really is a great charting tool.

pvictor commented 4 years ago

Hi, Yes there's currently no easy way to do it, only example of custom tootilp I have is this one : https://dreamrs.github.io/apexcharter/articles/advanced-configuration.html#scatter-plot

But it might be something easier to do by using htmltools.

What type of chart are you using ?

pvictor commented 4 years ago

Quick example of how it's possible with htmltools :

library(apexcharter)
library(htmltools)

# This function returns HTML as strings
make_tooltip <- function(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species) {
  tag <- tags$div(
    tags$div("This is a title", class = "apexcharts-tooltip-title"),
    tags$div(
      style = "padding: 10px;",
      "Some informations about this point:",
      tags$ul(
        tags$li("Sepal.Length:", tags$b(Sepal.Length)),
        tags$li("Sepal.Width:", tags$b(Sepal.Width)),
        tags$li("Petal.Length:", tags$b(Petal.Length)),
        tags$li("Petal.Width:", tags$b(Petal.Width)),
        tags$li("Species:", tags$b(Species))
      )
    )
  )
  doRenderTags(tag)
}

# Apply function over all columns and create a new variable
iris$tooltip <- mapply(
  FUN = make_tooltip,
  Sepal.Length = iris$Sepal.Length,
  Sepal.Width = iris$Sepal.Width, 
  Petal.Length = iris$Petal.Length, 
  Petal.Width = iris$Petal.Width,
  Species = iris$Species
)

# use "tooltip" variable in a custom aesthetic
apex(iris, aes(Sepal.Length, Sepal.Width, group = Species, tooltip = tooltip), type = "scatter") %>% 
  ax_tooltip(custom = JS(
    # return the value of variable "tooltip" when point is hovered
    "function({ series, seriesIndex, dataPointIndex, w }) {return w.config.series[seriesIndex].data[dataPointIndex].tooltip}"
  ))
OGuggenbuehl commented 4 years ago

Thank you very mich for the provided example, it helped me create my own tooltip. Unfortunately it is also missing information which was present in the default tooltip: The color of the group to which the observation in question belongs. Is there a way to re-implement this in the custom tooltip? Because it really is an essential piece of information.

I am using a scatterplot if that helps. I originally tried mapping the shape of the markers to a variable (so I could have either squares or circles depending on that variable) but that does not seem to be possible with Apexcharter, hence the need for a custom tooltip to include that piece of information.

Alik-V commented 4 years ago

Hi Victor,

I am having a similar problem and I cannot seem to get the code above working. I also tried to apply the code from your "advanced configuration" with no success. Would you mind advising what I am doing incorrectly? Using an example above:

library(tidyverse)
library(lubridate)
library(apexcharter)
library(htmltools)

dat <- tribble(
  ~Time,    ~value, ~Erosion,   ~Indications,
  "01/01/2019",  4571.00,   "0%",   "a",
  "01/09/2021",  4571.00,   "0%",   "a",
  "01/10/2021",  3794.00,   "-17%", "b",
  "01/11/2021",  3794.00,   "0%",   "b",
  "01/12/2021",  3604.00,   "-5%",  "c",
  "01/08/2023",  3604.00,   "0%",   "c",
  "01/09/2023",  3082.00,   "-14%", "d",
  "01/10/2023",  3082.00,   "0%",   "d",
  "01/12/2029",  3082.00,   "0%",   "d",
) %>%
  mutate(Time = dmy(Time),
         Feature = "treatment")

floor <- dat %>% 
  mutate(value = 1000,
         Indications = "None",
         Erosion = "0%",
         Feature = "floor")

dat <- bind_rows(dat, floor)

make_tooltip <- function(value, Indications, Erosion, Feature) {
  tag <- tags$div(
    tags$div("Date:", class = "apexcharts-tooltip-title"),
    tags$div(
      style = "padding: 10px;",
      "Some informations about this point:",
      tags$ul(
        tags$li("value", tags$b(value)),
        tags$li("Indications:", tags$b(Indications)),
        tags$li("Erosion:", tags$b(Erosion)),
        tags$li("Feature:", tags$b(Feature))

      )
    )
  )
  doRenderTags(tag)
}

dat$tooltip <- mapply(
  FUN = make_tooltip,
  value = dat$value,
  Indications = dat$Indications, 
  Erosion = dat$Erosion,
  Feature = dat$Feature
)

apex(data = dat, type = "line", 
     mapping = aes(x = Time, y = value, group = Feature, tooltip = tooltip)
) %>%
  ax_stroke(dashArray = c(0, 6)) %>%
  ax_colors(colors = c("#ffa500", "#000000")) %>%
  ax_tooltip(
    custom = JS(
      "function({ series, seriesIndex, dataPointIndex, w }) {return w.config.series[seriesIndex].data[dataPointIndex].tooltip}"
    )
  )

Using example from your advanced config page:

library(tidyverse)
library(lubridate)
library(apexcharter)
library(htmltools)

dat <- tribble(
  ~Time,    ~value, ~Erosion,   ~Indications,
  "01/01/2019",  4571.00,   "0%",   "a",
  "01/09/2021",  4571.00,   "0%",   "a",
  "01/10/2021",  3794.00,   "-17%", "b",
  "01/11/2021",  3794.00,   "0%",   "b",
  "01/12/2021",  3604.00,   "-5%",  "c",
  "01/08/2023",  3604.00,   "0%",   "c",
  "01/09/2023",  3082.00,   "-14%", "d",
  "01/10/2023",  3082.00,   "0%",   "d",
  "01/12/2029",  3082.00,   "0%",   "d",
) %>%
  mutate(Time = dmy(Time),
         Feature = "treatment")

floor <- dat %>% 
  mutate(value = 1000,
         Indications = "None",
         Erosion = "0%",
         Feature = "floor")

dat <- bind_rows(dat, floor)

apex(data = dat, type = "line", 
       mapping = aes(x = Time, y = value, group = Feature)
  ) %>%
    ax_stroke(dashArray = c(0, 6)) %>%
    ax_colors(colors = c("#ffa500", "#000000")) %>%
    ax_tooltip(
      custom = JS(
        paste(
          "function({ series, seriesIndex, dataPointIndex, w }) {",
          "console.log(w); return (",
          "'<div>' +",

          "'<div class = \"apexcharts-tooltip-title\">' +",
          "w.config.series[seriesIndex].data[dataPointIndex].label",
          "+ '</div>' +",
          "'<div style = \"padding: 5px;\">' +",
          "'<div class = \"apexcharts-tooltip-y-group\">' +",

          "'<span class = \"apexcharts-tooltip-text-label\">' +",
          "'Value: ' +",
          "'</span>' +",
          "'<span class = \"apexcharts-tooltip-text-value\">' +",
          "w.config.series[seriesIndex].data[dataPointIndex].x +",
          "'</span>' +",

          "'</br>' +",

          "'<span class = \"apexcharts-tooltip-text-label\">' +",
          "'Indications: ' +",
          "'</span>' +",
          "'<span class = \"apexcharts-tooltip-text-value\">' +",
          "w.config.series[seriesIndex].data[dataPointIndex].Indications +",
          "'</span>' +",

          "'</br>' +",

          "'<span class = \"apexcharts-tooltip-text-label\">' +",
          "'Erosion: ' +",
          "'</span>' +",
          "'<span class = \"apexcharts-tooltip-text-value\">' +",
          "w.config.series[seriesIndex].data[dataPointIndex].y +",
          "'</span>' +",

          "'</div>' +",
          "'</div>' +",

          "'</div>'",
          ");",
          "}", sep = "\n"
        )
      )
    )

I would appreciate any help on this!

pvictor commented 4 years ago

Hello, Yes there's still some work to do on tooltips, the complicated things is that's it's different according to type of charts.

Quick answer: in your first example try to replace .tooltip by [2], e.g. :

"function({ series, seriesIndex, dataPointIndex, w }) {return w.config.series[seriesIndex].data[dataPointIndex][2]}"

Is this better?

Alik-V commented 4 years ago

Worked like a charm! Thank you for super quick reply, Victor :)