You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shiny中双Highcharts同步问题:输入切换后JS点击事件失效

解决R Shiny中Highcharter图表双向同步失效问题

问题分析

你的代码存在三个核心问题导致切换单选框后同步失效:

  • 匹配标识不统一:地图点的name是州缩写(如CA),柱状图点的name是州全称(如California),根本无法匹配对应点
  • 实例遍历逻辑错误:Highcharts.charts会保留旧的图表实例,切换单选框后数组中存在无效实例,遍历会出错
  • 无状态重置:多次点击后红点残留,无法正确更新状态

修正后的完整代码

##PACKAGES
library(shiny)
library(shinyWidgets)
library(shinyjs)
library(dplyr)
library(tidyverse)
library(albersusa) ## remotes::install_github("hrbrmstr/albersusa")
library(highcharter)
library(usdata)
library(data.table)

states <- data.frame(
  name  = rep(state.abb,4),
  state = rep(state.name,4),
  metric = c(rep("YES",100),rep("NO",100)),
  value  = sample(100:5000,200)
)

# 修正后的同步JS逻辑
testJS <- JS("function() {
  // 获取当前点的州缩写:地图点直接取name,柱状图点取options.name
  const stateAbbr = this.name || this.options.name;
  if (!stateAbbr) return;
  
  // 定义两个图表的容器ID
  const chartIds = ['map1', 'bar1'];
  // 获取当前图表的容器ID
  const currentChartId = this.series.chart.container.id;
  // 定位目标图表ID
  const targetChartId = chartIds.find(id => id !== currentChartId);
  // 通过容器ID精准获取目标图表实例(过滤无效实例)
  const targetChart = Highcharts.charts.find(chart => chart?.container?.id === targetChartId);
  if (!targetChart) return;
  
  // 重置当前图表所有点为默认颜色
  this.series.chart.series.forEach(series => {
    series.points.forEach(point => {
      point.update({color: point.series.color}, false);
    });
  });
  // 重置目标图表所有点为默认颜色
  targetChart.series.forEach(series => {
    series.points.forEach(point => {
      point.update({color: point.series.color}, false);
    });
  });
  
  // 标记当前点击的点为红色
  this.update({color: 'red'}, false);
  
  // 在目标图表中找到对应州的点并标记为红色
  targetChart.series.forEach(series => {
    series.points.forEach(point => {
      const pointAbbr = point.name || point.options.name;
      if (pointAbbr === stateAbbr) {
        point.update({color: 'red'}, false);
      }
    });
  });
  
  // 统一重绘两个图表(提升性能)
  this.series.chart.redraw();
  targetChart.redraw();
}")

ui <- fluidPage(
  tags$script(src = "https://code.highcharts.com/mapdata/countries/us/us-all.js"),
  fluidRow(
    radioButtons(inputId = "toggle",label="toggle it", 
                 choices = c("YES","NO")),
    column(width=5,highchartOutput("map1")),
    column(width=5,highchartOutput("bar1"))
  )
)

server <- function(input, output, session) {
  
  # 处理数据:保留州缩写用于匹配
  df1_num<- reactive({
    states %>%
      filter(metric == input$toggle) %>%
      group_by(name) %>%
      mutate(
        first = dplyr::first(value),
        last = dplyr::last(value)
      ) %>%
      distinct(metric,state,name,first,last) %>% # 保留name列(州缩写)
      mutate(
        rate  = round(((last-first)/first)*100,1),
      )
  })
  
  # 地图图表
  output$map1 <- renderHighchart({
    hcmap("countries/us/us-all",
          data   = df1_num(),
          joinBy = c("hc-a2","name"),
          value  = "rate",
          borderColor = "#8d8d8d",
          nullColor = "#D3D3D3",
          download_map_data = FALSE
    ) %>%
      hc_plotOptions(series = list(
        point = list(
          events = list(
            click = testJS
          )
        )
      ))
  })
  
  # 柱状图图表:保留州缩写数据
  output$bar1 <- renderHighchart({
    test <- df1_num() %>%
      arrange(rate) %>%
      rowid_to_column("orderrate") %>%
      mutate(name = name) # 确保柱状图点携带州缩写信息
    
    highchart() %>%
      hc_add_series(
        data = test,
        hcaes(
          x     = state,
          y     = rate,
          group = orderrate,
          name  = name), # 绑定name属性为州缩写
        showInLegend = FALSE,
        type = "bar",
        color = "blue",
        polar = FALSE
      ) %>%
      hc_plotOptions(series = list(
        point = list(
          events = list(
            click = testJS
          )
        )
      ))
  })
}

shinyApp(ui = ui, server = server)

关键修改说明

  1. 统一匹配标识:在柱状图的hcaes中绑定name为州缩写,确保两个图表的点都能通过州缩写关联
  2. 精准定位图表实例:通过图表容器ID(map1/bar1)从Highcharts.charts中筛选有效实例,避免旧实例干扰
  3. 状态重置逻辑:每次点击前重置所有点的默认颜色,再标记对应点为红色,避免红点残留
  4. 批量更新+统一重绘:使用update(..., false)延迟重绘,最后统一调用redraw(),提升交互性能

内容的提问来源于stack exchange,提问作者jcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:31:05