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

如何在R Plotly中实现鼠标悬停高亮、移开自动取消高亮?

在R Plotly中实现鼠标悬停高亮、移开自动取消的方法

plotly::highlight函数的off参数确实没有直接支持鼠标移开的选项,要实现悬停触发高亮、移开自动取消的效果,我们可以通过自定义JavaScript事件处理来实现,借助htmlwidgets::onRender给Plotly图表添加原生的plotly_hover和plotly_unhover事件监听。

完整实现代码(基于ggplotly)

library(plotly)
library(htmlwidgets)
library(dplyr)

# 准备数据
df <- iris %>% mutate(key = row_number())

# 生成ggplot对象并转为plotly
gg <- df %>%
  ggplot(aes(Sepal.Length, Petal.Width)) +
  geom_point()

p <- ggplotly(gg)

# 添加自定义悬停高亮逻辑
p %>% onRender("
function(el, x) {
  // 保存每个trace的原始marker样式(尺寸、颜色)
  const originalMarkers = x.data.map(trace => ({
    size: trace.marker.size || 6, // 默认尺寸设为6,兼容未指定的情况
    color: trace.marker.color || '#1f77b4' // 默认颜色用Plotly的蓝色
  }));
  
  // 监听鼠标悬停事件
  el.on('plotly_hover', function(data) {
    const point = data.points[0];
    const traceIdx = point.curveNumber;
    const pointIdx = point.pointNumber;
    
    // 高亮当前点:放大尺寸+红色
    Plotly.restyle(el, {
      'marker.size': [[...Array(x.data[traceIdx].marker.size.length).fill(originalMarkers[traceIdx].size)], pointIdx, 15],
      'marker.color': [[...Array(x.data[traceIdx].marker.color.length).fill(originalMarkers[traceIdx].color)], pointIdx, '#ff0000']
    }, [traceIdx]);
  });
  
  // 监听鼠标移开事件
  el.on('plotly_unhover', function(data) {
    const point = data.points[0];
    const traceIdx = point.curveNumber;
    const pointIdx = point.pointNumber;
    
    // 恢复当前点的原始样式
    Plotly.restyle(el, {
      'marker.size': [[...Array(x.data[traceIdx].marker.size.length).fill(originalMarkers[traceIdx].size)], pointIdx, originalMarkers[traceIdx].size],
      'marker.color': [[...Array(x.data[traceIdx].marker.color.length).fill(originalMarkers[traceIdx].color)], pointIdx, originalMarkers[traceIdx].color]
    }, [traceIdx]);
  });
}
")

代码说明

  1. 保存原始样式:通过originalMarkers记录每个数据系列(trace)的原始marker尺寸和颜色,确保移开鼠标时能准确恢复样式。
  2. 悬停事件处理:当触发plotly_hover时,定位当前悬停的点,通过Plotly.restyle修改该点的尺寸(放大到15)和颜色(改为红色)实现高亮。
  3. 移开事件处理:触发plotly_unhover时,将当前点的样式恢复为之前保存的原始状态。

在Shiny中使用

直接将上述代码放入renderPlotly即可,示例如下:

library(shiny)

ui <- fluidPage(
  plotlyOutput("hoverHighlightPlot")
)

server <- function(input, output) {
  output$hoverHighlightPlot <- renderPlotly({
    # 这里放入上面生成p的完整代码
    df <- iris %>% mutate(key = row_number())
    gg <- df %>% ggplot(aes(Sepal.Length, Petal.Width)) + geom_point()
    p <- ggplotly(gg)
    p %>% onRender("
    function(el, x) {
      const originalMarkers = x.data.map(trace => ({
        size: trace.marker.size || 6,
        color: trace.marker.color || '#1f77b4'
      }));
      
      el.on('plotly_hover', function(data) {
        const point = data.points[0];
        const traceIdx = point.curveNumber;
        const pointIdx = point.pointNumber;
        
        Plotly.restyle(el, {
          'marker.size': [[...Array(x.data[traceIdx].marker.size.length).fill(originalMarkers[traceIdx].size)], pointIdx, 15],
          'marker.color': [[...Array(x.data[traceIdx].marker.color.length).fill(originalMarkers[traceIdx].color)], pointIdx, '#ff0000']
        }, [traceIdx]);
      });
      
      el.on('plotly_unhover', function(data) {
        const point = data.points[0];
        const traceIdx = point.curveNumber;
        const pointIdx = point.pointNumber;
        
        Plotly.restyle(el, {
          'marker.size': [[...Array(x.data[traceIdx].marker.size.length).fill(originalMarkers[traceIdx].size)], pointIdx, originalMarkers[traceIdx].size],
          'marker.color': [[...Array(x.data[traceIdx].marker.color.length).fill(originalMarkers[traceIdx].color)], pointIdx, originalMarkers[traceIdx].color]
        }, [traceIdx]);
      });
    }
    ")
  })
}

shinyApp(ui, server)

自定义高亮样式

你可以根据需求修改高亮的尺寸、颜色等参数:

  • 修改marker.size的15为你想要的高亮尺寸
  • 修改marker.color的#ff0000为你想要的高亮颜色

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 04:03:18