I want to reproduce the default tooltip with some additions. However, when I try to do so, it left-aligns both serie and group names, and I am not sure how to fix it.
Some sample data and what I tried to do:
library(dplyr)
library(echarts4r)
library(htmlwidgets)
set.seed(10)
data <- data.frame(name = rep(c("Bob", "Michael"), each = 10),
x = rep(0:9, 2),
y = sample(0:5, 20, replace = TRUE),
add = sample(1:100, 20, replace = TRUE))
# Default tooltip
data %>%
group_by(name) %>%
e_chart(x = x) %>%
e_line(serie = y) %>%
e_tooltip(trigger = "axis")
# My attempt to recreate the formatting while adding new things
data %>%
group_by(name) %>%
e_chart(x = x) %>%
e_line(serie = y, bind = add) %>%
e_tooltip(trigger = "axis",
formatter = JS("
function(params){
var colorSpan = color => `<span style='display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:` + color + `'></span>`;
let rez = '<strong>Day ' + params[0].value[0] + '</strong>';
params.forEach(item => {
var xx = '<br />' + colorSpan(item.color) + ' ' + item.seriesName +
' <strong>' + item.value[1] + '</strong> (' + item.name + ')'
rez += xx;
});
return (rez)}"))
So, the default tooltip looks like this (values are right aligned):
And my tooltip looks something like this, which is not very readable:
I want to add things to the tooltip while keeping the formatting mostly untouched, but do not know how to do so with right alignment. I am not very familiar with echarts and JS in general though, so I have some troubles with it.
EDIT
So, thanks to @Russ we now have a workaround, which is not exactly what I was hoping to get, but a solution nonetheless. Does not look as pretty as the default tooltip, but for now we have what we have.
Still, @Russ's solution does have some issues, so I post my edited version of his answer here. Not sure how to apply css to echarts' tooltip to remove margins caused by <pre>
tag, but that does not matter too much right now
# Adding whitespaces after the name
data <- data %>%
mutate(nameAlt = stringr::str_pad(name, max(nchar(name)), "right"))
data %>%
group_by(nameAlt) %>%
e_chart(x = x) %>%
e_line(serie = y, bind = add) %>%
e_tooltip(trigger = "axis",
formatter = JS("
function(params){
var colorSpan = color => `<span style='display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:` + color + `'></span>`;
let rez = '<strong>Day ' + params[0].value[0] + '</strong><pre>';
params.forEach(item => {
var xx = colorSpan(item.color) + item.seriesName +
'<span style=`float:right;margin-left:20px;`><strong>' + item.value[1] + '</strong> (' + item.name + ')</span></br>'
rez += xx;
});
rez += '</pre>'
return (rez)}")) %>%
# Removing whitespaces from the legend
e_legend(formatter = JS("function(name){return(name.trim())}"))
Result:
The way to solve this is with a combination of html tags with css styles that you can specify inside of the javascript. I tried playing around with it and came up a solution that does what you want at the cost of changing the font and probably not being best practice html/css. So my solution isn't a great one, but it does fix the spacing and keep most of your original formatting.
What I did was use R to add white space to the end of Bob's name so that his name has the same number of characters as Michael's name. So like "Bob"
becomes "Bob "
. I wrote the code so that it finds the longest name in the data and then adds a variable amount of white space to all the other names so that they're all the same length. It should work with an arbitrary number of names.
Then I added a <pre></pre>
html tag around the rows in the tool tip. I put <span></span>
tags around the numbers in each row and then defined a style that included a bit of a left side margin to separate Bob and Michael from the numbers.
# Find the longest name in the data
longest_name_length <- data$name %>% # names column
unique() %>% # unique values in the name column
nchar() %>% # number of characters in each unique name
max(na.rm = TRUE) # longest name
# add a new column with the length of the name
data$name_length <- data$name %>%
nchar()
# add a characters to add column
data$characters_to_add <- longest_name_length - data$name_length
# add white space to the shorter characters so that all names are the same length
# add a variable amount of white space to each name using a loop
for (row in 1:nrow(data)){
# Rep " " by the number of characters to add and then collapse
# that vector into a single string using paste
white_spaces <- rep(" ", times=data$characters_to_add[row]) %>%
paste(collapse = "")
# paste the name to the white spaces string
data$name[row] <- paste0(data$name[row], white_spaces)
}
data %>%
group_by(name) %>%
e_chart(x = x) %>%
e_line(serie = y, bind = add) %>%
e_tooltip(trigger = "axis",
formatter = JS("
function(params){
var colorSpan = color => `<span style='display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:` + color + `'></span>`;
let rez = '<strong>Day ' + params[0].value[0] + '</strong>';
params.forEach(item => {
var xx = '<pre>' + colorSpan(item.color) + item.seriesName +
'<span style=`float:right;margin-left:15px;`> <strong>' + item.value[1] + '</strong> (' + item.name + ')</span></pre>'
rez += xx;
});
return (rez)}"))
In this part var xx = '<br />' +
I replaced a </br>
tag with a <pre>
and then in this part
'</strong> (' + item.name + ')'
I added ended a </pre>
to close the tag. Around this part
<strong>' + item.value[1] + '</strong> (' + item.name + ')
I added tags to group these items into an inline html element and then inside I specified a left margin using css to add space between Bob/Michael and their numbers with this style=`float:right;margin-left:15px;`
This is a javascript question, but it's also an html/css question. It might be worth it to add those tags and hope for a less hacky solution than mine :D