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

求助:R Plotly散点地图(scattermapbox)悬停显示图片失效

问题背景

我参考Stack Overflow上的示例实现了R Plotly散点图中鼠标悬停显示图片的功能,该方案在散点图中正常运行,但切换为scattermapbox地图时失效,需要修改代码使其适配Plotly地图。


原始代码(含依赖与JS逻辑)

library(dplyr)
library(plotly)

df <- data.frame(x = c(-81.026, -81.025, -81.028), y = c(44.13, 44.14, 44.15), 
     url = c("https://upload.wikimedia.org/wikipedia/commons/6/6f/Beethoven.jpg",
        "https://upload.wikimedia.org/wikipedia/commons/4/47/Croce-Mozart-Detail.jpg",
        "https://upload.wikimedia.org/wikipedia/commons/6/6a/Johann_Sebastian_Bach.jpg"))

d3 <- htmltools::htmlDependency(
  "d3", "7.3",
  src = c(href = "https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/"),
  script = "d3.min.js"
)

js <- '
function(el) {
  var tooltip = d3.select("#" + el.id + " .svg-container")
    .append("div")
    .attr("class", "my-custom-tooltip");

  el.on("plotly_hover", function(d) {
    var pt = d.points[0];
    var x = pt.xaxis.range[0];
    var y = pt.yaxis.range[1];
    var xPixel = pt.xaxis.l2p(x) + pt.xaxis._offset;
    var yPixel = pt.yaxis.l2p(y) + pt.yaxis._offset;
    var img = "<img src=\\\"" +  pt.customdata + "\\\" width=100>";
    tooltip.html(img)
      .style("position", "absolute")
      .style("left", xPixel + "px")
      .style("top", yPixel + "px");
    tooltip.transition()
      .duration(300)
      .style("opacity", 1);
  });

  el.on("plotly_unhover", function(d) {
    tooltip.transition()
      .duration(500)
      .style("opacity", 0);
  });
}
'

可正常运行的散点图代码

p <-plot_ly(df, x = ~x, y = ~y, type = "scatter", mode = "markers", hoverinfo = ~x, customdata = ~url) %>%
  htmlwidgets::onRender(js)

p$dependencies <- c(p$dependencies, list(d3))
p

失效的scattermapbox地图代码

p <- plot_ly(df, lon = ~x, lat = ~y, type = "scattermapbox", mode = "markers", hoverinfo = ~x, customdata = ~url) %>%
  layout(mapbox = list(style = "white-bg", sourcetype = 'raster', zoom = 4,
                      center = list(lon = -81 ,lat= 44),
                      layers = list(list(below = 'traces', sourcetype = "raster",
                                         source = list("https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}"))))) %>%
  htmlwidgets::onRender(js)

p$dependencies <- c(p$dependencies, list(d3))
p

解决方案(修改后的代码)

修改后的JS逻辑

scattermapbox基于Mapbox GL,DOM结构和坐标体系与普通散点图不同,需调整容器选择和坐标计算方式:

js <- '
function(el) {
  // 选择地图专属容器,替代原svg容器
  var tooltip = d3.select("#" + el.id + " .mapboxgl-canvas-container")
    .append("div")
    .attr("class", "my-custom-tooltip")
    .style("opacity", 0)
    .style("position", "absolute")
    .style("pointer-events", "none")
    .style("z-index", 1000);

  el.on("plotly_hover", function(d) {
    var pt = d.points[0];
    // 直接使用鼠标的屏幕坐标定位tooltip
    var mouseX = d.event.clientX;
    var mouseY = d.event.clientY;
    var img = "<img src=\\\"" + pt.customdata + "\\\" width=100>";
    
    tooltip.html(img)
      .style("left", (mouseX + 10) + "px")
      .style("top", (mouseY + 10) + "px");
    
    tooltip.transition()
      .duration(300)
      .style("opacity", 1);
  });

  el.on("plotly_unhover", function(d) {
    tooltip.transition()
      .duration(500)
      .style("opacity", 0);
  });
}
'

修改后的地图代码

p <- plot_ly(df, lon = ~x, lat = ~y, type = "scattermapbox", mode = "markers", hoverinfo = "none", customdata = ~url) %>%
  layout(mapbox = list(style = "white-bg", sourcetype = 'raster', zoom = 12,
                      center = list(lon = -81.026 ,lat= 44.14),
                      layers = list(list(below = 'traces', sourcetype = "raster",
                                         source = list("https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}"))))) %>%
  htmlwidgets::onRender(js)

p$dependencies <- c(p$dependencies, list(d3))
p

修改说明

  • 容器适配:替换为Mapbox专属的.mapboxgl-canvas-container容器,匹配地图的DOM结构
  • 坐标逻辑:使用鼠标事件的clientX/clientY直接获取屏幕坐标,避免依赖散点图的xaxis/yaxis对象
  • 样式优化:添加pointer-events: none防止tooltip遮挡鼠标交互,设置z-index确保tooltip显示在地图上方;关闭默认tooltip避免冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 05:14:58