当前位置: 首页 > 知识库问答 >
问题:

在绘图仪中,根据坐标值而不是像素设置标记大小

空成天
2023-03-14

不幸的是,这篇文章用plotly设置了标记大小,这对我所寻找的内容没有帮助,而且是我能找到的关于这个主题的唯一一篇文章。根据散点图尺寸参数的plotly文档:

大小(大于或等于0的数字或数字数组),默认值:6,设置标记大小(以像素为单位)

(在px中)对我来说是个问题。我想创建一个绘图,其中标记大小基于坐标值,而不是像素,这样我可以增加图形的大小(例如,通过完全屏蔽),并且点的大小也会增加。我目前的代码示例如下:

library(plotly)
mydf <- data.frame(x = rep(1:20, times = 20), y = rep(1:20, each = 20),
                   thesize = 10)
plot_ly(mydf) %>%
  add_trace(x = ~x, y = ~y, type = 'scatter', mode = 'markers', 
            marker = list(symbol = 'hexagon', size = ~thesize, opacity = 0.6))

如果您在R中创建此图,然后通过拖动RStudio查看器窗口或以其他方式使图变大或变小,您会注意到标记保持完全相同的大小(10像素),这令人沮丧。如果我能让这些标记的直径==1(在x轴上),而不是设置为像素数,我会很高兴。这有可能吗?

任何帮助都是超级感谢!!!

共有1个答案

晋鹤轩
2023-03-14

>

  • 让我们从定义轴范围的绘图开始。

    p <- plot_ly() %>% layout(xaxis = list(range = c(1, 5)))
    

    现在添加一个JavaScript eventlistener,用于捕获绘图布局中的任何更改

    javascript <- "
    var myPlot = document.getElementsByClassName('plotly')[0];
    
    function resize(eventdata) {
      // magic happens here
    }
    
    myPlot.on('plotly_relayout', function(eventdata) {
      resize(eventdata);
    });
    "
    p <- htmlwidgets::prependContent(p, 
                                     onStaticRenderComplete(javascript))
    p
    

    事件通过eventdata,我们可以从中获得新的轴范围。

    eventdata['xaxis.range[1]']
    

    因为我们事先不知道图的大小,所以我们通过轴心线的大小来确定它

    var plot_width = Plotly.d3.select('.xlines-above').node().getBBox()['width'];
    

    我们需要手动调用该事件一次,以确保绘图已正确初始化

    放大

    library("plotly")
    library("htmlwidgets")
    
    p <- plot_ly() %>%
      add_trace(x = c(1.5, 3, 4.2),
                y = c(-2, 1, 2), 
                type = 'scatter',
                mode = 'lines+markers',
                showlegend = F) %>% 
      add_trace(x = c(2, 3, 4.2),
                y = c(2, 0, -1),
                type = 'scatter',
                mode = 'lines+markers',
                showlegend = F) %>%
      add_trace(x = c(1.5, 3, 4.2),
                y = c(1, 0.5, 1),
                type = 'scatter',
                mode = 'markers',
                showlegend = F) %>% 
      layout(xaxis = list(range = c(1, 5)))
    javascript <- "
    marker_size = 0.5; // x-axis units
    var myPlot = document.getElementsByClassName('plotly')[0];
    
    function resize(eventdata) {
      var xaxis_stop = 5;
      var xaxis_start = 1;
      var plot_width = Plotly.d3.select('.xlines-above').node().getBBox()['width'];
      if (eventdata['xaxis.range[1]'] !== undefined) {
        var update = {'marker.size': marker_size * plot_width / (eventdata['xaxis.range[1]'] - eventdata['xaxis.range[0]'])};
      } else {
        var update = {'marker.size': marker_size * plot_width / (xaxis_stop - xaxis_start)};
      }
      Plotly.restyle(myPlot, update, 2);
    }
    resize({eventdata: {}});
    
    myPlot.on('plotly_relayout', function(eventdata) {
      resize(eventdata);
    });
    "
    p <- htmlwidgets::prependContent(p, 
                                     onStaticRenderComplete(javascript))
    p
    

    交互式JavaScript示例

    • 您可以从图形的定义高度/宽度和定义的轴范围开始,这样您就可以知道一个轴单位有多少像素
    • 标记的大小最初是您想要的大小
    • 每当用户更改轴范围时,将触发plotly\u relayout事件,您可以从xaxis.range[1](开始)和xaxis.range[1](结束)
    • 中的 eventdata检索新范围
    • 根据新范围,您可以重新显示标记大小
    var plot_width = 500;
    var plot_height = 500;
    var margin_l = 100;
    var margin_r = 100;
    marker_size = 0.5; // x-axis units
    xaxis_start = 1;
    xaxis_stop = 5;
    
    var trace1 = {
      x: [1.5, 2, 3, 4],
      y: [10, 15, 13, 17],
      mode: "markers",
      marker: {
        size: marker_size *
          (plot_width - margin_l - margin_r) /
          (xaxis_stop - xaxis_start)
      },
      showlegend: false
    };
    
    var trace2 = {
      x: [2, 3, 4, 4.5],
      y: [16, 5, 11, 10],
      mode: "lines"
    };
    
    var trace3 = {
      x: [1.5, 2, 3, 4],
      y: [12, 9, 15, 12],
      mode: "lines+markers",
      showlegend: false
    };
    
    var data = [trace1, trace2, trace3];
    
    var layout = {
      width: plot_width,
      height: plot_height,
      margin: {
        l: margin_l,
        r: margin_r
      },
      xaxis: {
        range: [1, 5]
      },
      showlegend: false
    };
    
    Plotly.newPlot("myDiv", data, layout);
    
    var refplot = document.getElementById("myDiv");
    refplot.on("plotly_relayout", function(eventdata) {
      if (eventdata["xaxis.range[1]"] !== undefined) {
        var update = {
          "marker.size": marker_size *
            (plot_width - margin_l - margin_r) /
            (eventdata["xaxis.range[1]"] - eventdata["xaxis.range[0]"])
        };
      } else {
        var update = {
          "marker.size": marker_size *
            (plot_width - margin_l - margin_r) /
            (xaxis_stop - xaxis_start)
        };
      }
      Plotly.restyle("myDiv", update, 0);
    });
    <head>
      <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    </head>
    
    <body>
      <div id="myDiv"></div>
    </body>

  •  类似资料:
    • 好吧,这可能有点愚蠢,但我真的很难理解Matlab中的图像坐标。 所以,在一个数学方程中,f(x,y)f是图像函数,其中x和y是图像的坐标。例如,在matlab代码中,我们可以: 其中,img(1,4)等效于函数f(x,y)。现在,在Matlab中,有一个选项可以使用cart2pol()函数将笛卡尔坐标(x,y)转换为极坐标(rho,theta)。 现在,这就是我不明白的地方。是否可以应用f(ρ,

    • 问题内容: 作为我对登录功能的Selenium测试的一部分,我想通过识别按钮的坐标并指示Selenium单击这些坐标来单击按钮。无需标识元素本身即可完成此操作(通过id,xpath等)。 我知道还有其他更有效的方式来运行click命令,但是我希望专门使用这种方法来最好地匹配用户体验。谢谢。 问题答案: 硒不会让你这样做。

    • 我写了一个代码,在选项卡式窗格中显示图像。我的代码如下所示 好吧,然后我需要在图像的特定位置放置一个标记…如何在上面放置标记…? 任何关于在图像中放置标记的帮助都是受欢迎的....

    • 我在FrameLayout中的SurfaceView画布上画线。我从相机预览中接收图像,对其进行处理,获取矩形的坐标并在画布上绘制线条。绘制时,我得到这些线在y轴上的位移,线越低,位移越大(见下面的照片): 用红线标记(使用Paint程序,而不是实际的应用程序)下线坐标坐标在位图上的大致位置,矩形的下部绿线(由实际的应用程序放置,在画布上绘制)以及红线显示,坐标移位了多少。顶部的坐标不能穿过屏幕,

    • 我已经完成了learnopengl突破系列中的几个教程。com,所以我有一个非常简单的2D渲染器。不过,我想给它添加一个子图像功能,在这里我可以为一种“源矩形”指定一个vec4,因此如果vec4是,它将只渲染一个宽度和高度为32的10,10的矩形,有点像SDL渲染器的工作方式。 渲染器的设置方式是所有精灵都使用一个包含纹理坐标的四边形VAO。起初,我认为我可以为每个精灵使用一个VAO数组,每个都有

    • 我有一个包含坐标的.csv文件,我需要在我做过的地图上使用python绘制它们。有人能帮我吗?