Я пытаюсь использовать echarts4rProxy для динамического добавления и удаления выделения и маркеров из графика в Shiny. Я не уверен, что понимаю, как правильно использовать serie_index при добавлении маркера, поскольку он делает странные вещи, если у меня serie_index равно чему-либо, кроме 1.
Этот пост на SO очень помог мне научиться удалять маркеры.
В основном он делает то, что я хочу, когда у меня есть serie_index = 1, за исключением случаев, когда я отключаю первую серию в легенде, а затем запрашиваю выделить/показать маркер другой серии. Тогда он вообще больше не сможет показывать маркер на правильной строке.
На этом рисунке группа F правильно выделена/отмечена:
Но когда первая группа (D) в легенде отключена, хотя она и правильно подсвечивает F, маркер не отображается:
А когда serie_index == linenum вместо 1, он делает странные вещи и показывает несколько маркеров после того, как вы сделали разные выборки.
Пример кода ниже:
library(shiny)
library(plotly)
library(data.table)
library(echarts4r)
dt <- as.data.table(copy(diamonds))
dt <- unique(dt[color %in% c("D", "E", "F") & cut == "Premium"], by = c("cut", "color", "clarity"))
setorder(dt, clarity)
# Function to remove all markers on an echarts plot
e_remove_mark_p <- function (proxy) {
opts <- list(id = proxy$id)
proxy$session$sendCustomMessage("e_remove_mark_p", opts)
return(proxy)
}
ui <- fluidPage(
# Javascript to remove all markers on an echarts plot
tags$head(
tags$script(HTML("
Shiny.addCustomMessageHandler('e_remove_mark_p',
function(data) {
var chart = get_e_charts(data.id);
let opts = chart.getOption();
if (opts.markPoint.length > 0) {
opts.markPoint.length = 0; /* remove data */
}
chart.setOption(opts, true);
})
"))),
fluidRow(radioButtons("line", label = "Focus on line", choices = c("D", "E", "F", "None"), selected = "None")),
fluidRow(echarts4rOutput("plot"))
)
server <- function(input, output, session) {
# Create plot
output$plot <- renderEcharts4r({
dt |>
group_by(color) |>
e_charts(clarity) |>
e_line(price,
legendHoverLink = T,
emphasis = list(disabled = F, focus = "series", blurScope = "coordinateSystem", lineStyle = list(width = 2))) |>
e_tooltip(trigger = "item")
})
# Proxy plot to highlight and show a marker for the selected line
observe({
echarts4rProxy("plot") |>
e_downplay_p()
echarts4rProxy("plot", data = NULL) %>%
e_remove_mark_p()
if (input$line != "None") {
linename <- input$line
linenum <- which(c("D", "E", "F") %in% input$line)
tmp <- dt[color == linename]
echarts4rProxy("plot") |>
e_highlight_p(series_name = linename)
echarts4rProxy("plot", data = NULL) |>
e_mark_p(
# serie_index = linenum,
serie_index = 1,
data = list(yAxis = tmp[clarity == "IF", price],
xAxis = tmp[clarity == "IF", clarity],
value = tmp[clarity == "IF", price]
),
itemStyle = list(color = "red")) |>
e_merge()
} else {
echarts4rProxy("plot") |>
e_downplay_p()
echarts4rProxy("plot", data = NULL) %>%
e_remove_mark_p()
}
})
}
shinyApp(ui, server)





Первая проблема с отсутствующими маркерами связана с serie_index = 1, который нужно изменить на serie_index = linenum, как вы уже предложили.
Возникающая тогда проблема с несколькими маркерами связана с тем, что js, который используется для удаления маркеров (opts.markPoint.length = 0;), недостаточно строг, его необходимо расширить до чего-то вроде
opts.series.map(function(e) {
e.markPoint = null;
})
Тогда это будет работать:
library(shiny)
library(plotly)
library(data.table)
library(echarts4r)
dt <- as.data.table(copy(diamonds))
dt <- unique(dt[color %in% c("D", "E", "F") & cut == "Premium"], by = c("cut", "color", "clarity"))
setorder(dt, clarity)
# Function to remove all markers on an echarts plot
e_remove_mark_p <- function (proxy) {
opts <- list(id = proxy$id)
proxy$session$sendCustomMessage("e_remove_mark_p", opts)
return(proxy)
}
ui <- fluidPage(
# Javascript to remove all markers on an echarts plot
tags$head(
tags$script(HTML("
Shiny.addCustomMessageHandler('e_remove_mark_p',
function(data) {
var chart = get_e_charts(data.id);
let opts = chart.getOption();
if (opts.series.length > 0) {
opts.markPoint.length = 0;
opts.series.map(function(e) {
e.markPoint = null;
})
}
chart.setOption(opts, true);
})
"))),
fluidRow(radioButtons("line", label = "Focus on line", choices = c("D", "E", "F", "None"), selected = "None")),
fluidRow(echarts4rOutput("plot"))
)
server <- function(input, output, session) {
# Create plot
output$plot <- renderEcharts4r({
dt |>
group_by(color) |>
e_charts(clarity) |>
e_line(price,
legendHoverLink = T,
emphasis = list(disabled = F, focus = "series", blurScope = "coordinateSystem", lineStyle = list(width = 2))) |>
e_tooltip(trigger = "item")
})
# Proxy plot to highlight and show a marker for the selected line
observe({
echarts4rProxy("plot") |>
e_downplay_p()
echarts4rProxy("plot", data = NULL) %>%
e_remove_mark_p()
if (input$line != "None") {
linename <- input$line
linenum <- which(c("D", "E", "F") %in% input$line)
tmp <- dt[color == linename]
echarts4rProxy("plot") |>
e_highlight_p(series_name = linename)
echarts4rProxy("plot", data = NULL) |>
e_mark_p(
serie_index = linenum,
data = list(yAxis = tmp[clarity == "IF", price],
xAxis = tmp[clarity == "IF", clarity],
value = tmp[clarity == "IF", price]
),
itemStyle = list(color = "red")) |>
e_merge()
} else {
echarts4rProxy("plot") |>
e_downplay_p()
echarts4rProxy("plot", data = NULL) %>%
e_remove_mark_p()
}
})
}
shinyApp(ui, server)
Спасибо, это отлично работает! Конечно, было бы полезно, если бы я знал что-нибудь о JavaScript, эй.