javascript - 改变R Shiny 的plotly scatter3d中的单个点

标签 javascript r shiny plotly

我有一个应用程序,我正在尝试更改点的大小、颜色或符号。 该点是用户单击的对象。 单击一个点会在我的程序中创建一个弹出窗口,其中显示链接到属于所单击点的行号的列中的 ID 值的另一个数据集。我在演示应用程序中包含了点击事件的事件流程(没有弹出窗口)。

我正在尝试根据答案 here 更改观点绘制二维散点图。然而,将代码应用到我的 3d 图似乎不起作用。

一些额外的背景信息:我正在构建一个程序来分析 3D 散点数据,我的应用程序包含其中几个 3D 绘图

有人知道如何实现这个功能吗?

下面的应用程序包含 2d(注释)和 3d 绘图对象的代码,以显示工作和非工作情况,并且是对 @Maximilian Peters 给出的代码的直接修改

感谢您的帮助!

额外问题: 假设我们可以使其适用于 3dplot,我还想弄清楚如何更改 JavaScript 代码以根据存储在 a 中的数字更改点 react 变量(即values$activepoint)而不是来自点击事件,因为我将允许用户使用 <- 和 -> 按钮循环浏览点,该按钮更改我们从中检索附加信息的点 ID。

library(shiny)
library(plotly)
library(htmlwidgets)

ui <- fluidPage(
  plotlyOutput("plot"),
  textOutput('messageNr')
)

javascript <- "
function(el, x){
el.on('plotly_click', function(data) {
colors = [];
var base_color = document.getElementsByClassName('legendpoints')[data.points[0].curveNumber].getElementsByTagName('path')[0].style['stroke']
for (var i = 0; i < data.points[0].data.x.length; i += 1) {
colors.push(base_color)
};
colors[data.points[0].pointNumber] = '#000000';
Plotly.restyle(el, 
{'marker':{color: colors}}, 
[data.points[0].curveNumber]
);
//make sure all the other traces get back their original color
for (i = 0; i < document.getElementsByClassName('plotly')[0].data.length; i += 1) {
if (i != data.points[0].curveNumber) {
colors = [];
base_color = document.getElementsByClassName('legendpoints')[i].getElementsByTagName('path')[0].style['stroke'];
for (var p = 0; p < document.getElementsByClassName('plotly')[0].data[i].x.length; p += 1) {
colors.push(base_color);
}
Plotly.restyle(el, 
{'marker':{color: colors}}, 
[i]);
}
};
});
}"


server <- function(input, output, session) {
  row.names(mtcars) <- 1:nrow(mtcars)
  colorscale <- c("blue", "red", "yellow")

  values <- reactiveValues()

  output$plot <- renderPlotly({
    values$point <- event_data("plotly_click", source = "select")

  plot_ly(mtcars,
          x = ~mpg,
          y = ~cyl,
          z = ~wt,
          type = "scatter3d",
          color = as.factor(mtcars$gear),
          colors = colorscale,
          mode = "markers",
          source = "select",
          showlegend = F)%>%
    add_markers() %>% onRender(javascript)
  } )



observeEvent(values$point, {
  values$row <- as.numeric(values$point$pointNumber) +1
   values$ID <- rownames(mtcars)[values$row]
   ### the values$ID is what I use to look up the corresponding dataset in other dataframes containing the detailed info of a datapoint in the 
   ### summary data set that is used to create the real scatter3d plots in which the user clicks. 
  output$messageNr <- renderText(values$ID)
  })
 }

# server <- function(input, output, session) {
# 
#   nms <- row.names(mtcars)
# 
#   output$plot <- renderPlotly({
#     p <- ggplot(mtcars, aes(x = mpg, y = wt, col = as.factor(cyl))) +
#       geom_point()
#     ggplotly(p) %>% onRender(javascript)
# 
#   })
# }

shinyApp(ui, server)

最佳答案

您可以添加一条轨迹来突出显示该点,更改单个点的位置以响应 Javascript eventListener

library(shiny)
library(plotly)
library(htmlwidgets)

ui <- fluidPage(
  plotlyOutput("plot"),
  textOutput('messageNr')
)

javascript <- "
function(el, x) {
  el.on('plotly_click', function(data) {

    var highlight_trace = el.data.length - 1;
    //the coordinates of the point which was clicked on
    //is found in data
    var newPoint = {x: data.points[0].x,
                    y: data.points[0].y,
                    z: data.points[0].z};

    //update the plot data and redraw it
    if (el.data[highlight_trace].x[0] != newPoint.x ||
        el.data[highlight_trace].y[0] != newPoint.y ||
        el.data[highlight_trace].z[0] != newPoint.z) {
      el.data[highlight_trace].x[0] = newPoint.x;
      el.data[highlight_trace].y[0] = newPoint.y      
      el.data[highlight_trace].z[0] = newPoint.z
      Plotly.redraw(el);
      }
  })
}
"


server <- function(input, output, session) {

  output$plot <- renderPlotly(
    {
      p <- plot_ly()
      p <- add_trace(p,
              data = mtcars,
              x = ~mpg,
              y = ~cyl,
              z = ~wt,
              color = as.factor(mtcars$gear),
              type = 'scatter3d',
              mode = "markers")
      p <- add_trace(p, 
                     x = c(20), 
                     y = c(5), 
                     z = c(4), 
                     name = 'highlight',
                     type = 'scatter3d',
                     mode = 'markers',
                     marker = list(size = 15,
                                   opacity = 0.5)) %>% onRender(javascript)
      p
    } 
  )
}

shinyApp(ui, server)
  • el 是存储绘图的 JavaScript 元素
  • “el.data”是 Plotly 存储绘图数据的位置
  • if block 确保仅在单击新点时才重新绘制图形
  • 如果单击某个点,突出显示轨迹的数据将被覆盖,并且绘图将重绘n

注释

  • 请确保您使用的是最新版本的 Plotly,否则点击事件可能无法正常工作或出现错误
  • 在您的原始代码中,跟踪被绘制了多次(删除 showlegend 才能看到它),可能是因为 add_markers()

交互式 JavaScript 示例

Plotly.d3.csv('https://raw.githubusercontent.com/plotly/datasets/master/3d-scatter.csv', function(err, rows) {
      function unpack(rows, key) {
        return rows.map(function(row) {
          return row[key];
        });
      }
      var trace1 = {
        x: unpack(rows, 'x1').slice(0, 30),
        y: unpack(rows, 'y1').slice(0, 30),
        z: unpack(rows, 'z1').slice(0, 30),
        mode: 'markers',
        marker: {
          size: 12,
          line: {
            color: 'rgba(217, 217, 217, 0.14)',
            width: 0.5
          },
          opacity: 0.8
        },
        type: 'scatter3d'
      };

      var trace3 = {
        x: [0],
        y: [0],
        z: [0],
        name: 'highlight',
        mode: 'markers',
        type: 'scatter3d',
        marker: {
          size: 24,
          opacity: 0.5
        }
      };
      var data = [trace1, trace3];
      var layout = {
        margin: {
          l: 0,
          r: 0,
          b: 0,
          t: 0
        }
      };
      
      myDiv = document.getElementById('myDiv');
      Plotly.newPlot(myDiv, data);

      myDiv.on('plotly_click', function(data) {
        var highlight_trace = myDiv.data.length - 1;
        //the coordinates of the point which was clicked on
        //is found in data
        var newPoint = {
          x: data.points[0].x,
          y: data.points[0].y,
          z: data.points[0].z
        };

        //update the plot data and redraw it
        if (myDiv.data[highlight_trace].x[0] != newPoint.x ||
          myDiv.data[highlight_trace].y[0] != newPoint.y ||
          myDiv.data[highlight_trace].z[0] != newPoint.z) {
          myDiv.data[highlight_trace].x[0] = newPoint.x;
          myDiv.data[highlight_trace].y[0] = newPoint.y
          myDiv.data[highlight_trace].z[0] = newPoint.z
          Plotly.redraw(myDiv);
        }
      });


    })
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id='myDiv'></div>

关于javascript - 改变R Shiny 的plotly scatter3d中的单个点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47365402/

相关文章:

javascript - 绕过观看多个视频的 6 次下载限制

javascript - 如何将 HTML 链接定向到 R Shiny 中的侧边栏项目

r - 访问通过 file() 创建的文件连接的属性

r - 更改选项卡面板时显示 Shiny 正忙(或正在加载)

css - 更改数据表过滤器下拉框的颜色

r - 使用 Shiny 在 Google Sheet 中收集用户数据

r - 在 Shiny 的 R 应用程序中显示欧元符号

javascript - AngularJS - 客户有单独的 MongoDB 数据库

javascript - 如何在本地测试 firebase onCall()?

javascript - 当 Tab 更改时,React Native TextInput 值仍然存在