Plotly.js 点击添加点 2022

Plotly.js Adding Point on Click 2022

我有兴趣在 plotly.js 中创建一个交互式绘图,用户可以在其中单击绘图并在该位置添加一个新点。本质上,这意味着检索鼠标单击的绘图坐标。大多数内置点击事件处理捕获对已绘制标记的点击,而不是绘图中的任意位置。

以下问题涉及此问题,。但是,代码似乎在某些时候因 plotly.js 的更改而变得过时。该问题的答案示例在 codepen 上进行了演示。看来 xy 鼠标位置检测现在仅在工具栏区域内更新。我的猜测是对构成情节的各个部分进行了重命名。

Link 到该答案的注释中的非功能代码: https://codepen.io/circleoncircles/pen/abObLLE

var traces = [{
  x: [1, 2, 3, 4],
  y: [10, 15, 13, 17],
  mode: 'markers',
  type: 'scatter'
}];

traces.push({
  x: [2, 3, 4, 5],
  y: [16, 5, 11, 9],
  mode: 'markers',
  type: 'scatter'
});

traces.push({
  x: [1, 2, 3, 4],
  y: [12, 9, 15, 12],
  mode: 'markers',
  type: 'scatter'
});

traces.push({
  x: [],
  y: [],
  mode: 'markers',
  type: 'scatter'
});

var myPlot = document.getElementById('myPlot')
Plotly.newPlot('myPlot', traces, {hovermode: 'closest'});

Number.prototype.between = function(min, max) {
  return this >= min && this <= max;
};


Plotly.d3.select(".plotly").on('click', function(d, i) {
  var e = Plotly.d3.event;
  var bg = document.getElementsByClassName('bg')[0];
  var x = ((e.layerX - bg.attributes['x'].value + 4) / (bg.attributes['width'].value)) * (myPlot.layout.xaxis.range[1] - myPlot.layout.xaxis.range[0]) + myPlot.layout.xaxis.range[0];
  var y = ((e.layerY - bg.attributes['y'].value + 4) / (bg.attributes['height'].value)) * (myPlot.layout.yaxis.range[0] - myPlot.layout.yaxis.range[1]) + myPlot.layout.yaxis.range[1]
  if (x.between(myPlot.layout.xaxis.range[0], myPlot.layout.xaxis.range[1]) &&
    y.between(myPlot.layout.yaxis.range[0], myPlot.layout.yaxis.range[1])) {
    Plotly.extendTraces(myPlot, {
      x: [
        [x]
      ],
      y: [
        [y]
      ]
    }, [3]);
  }
});

Plotly.d3.select(".plotly").on('mousemove', function(d, i) {
  var e = Plotly.d3.event;
  var bg = document.getElementsByClassName('bg')[0];
  var x = ((e.layerX - bg.attributes['x'].value + 4) / (bg.attributes['width'].value)) * (myPlot.layout.xaxis.range[1] - myPlot.layout.xaxis.range[0]) + myPlot.layout.xaxis.range[0];
  var y = ((e.layerY - bg.attributes['y'].value + 4) / (bg.attributes['height'].value)) * (myPlot.layout.yaxis.range[0] - myPlot.layout.yaxis.range[1]) + myPlot.layout.yaxis.range[1]
  if (x.between(myPlot.layout.xaxis.range[0], myPlot.layout.xaxis.range[1]) &&
    y.between(myPlot.layout.yaxis.range[0], myPlot.layout.yaxis.range[1])) {
    console.log("Location X:"+x+" Y"+y)
   document.getElementById("xvalue").value = x;
   document.getElementById("yvalue").value = y;
  }
});

有人有更新的方法吗?

我想我明白了。我仍然认为这相对 hacky,所以如果其他人有更好的方法来处理它,我会洗耳恭听,并很乐意分配一个更好的答案。

您真正需要做的就是获取表示绘图字段的元素的边界框。看起来这样的元素之一就是 class gridlayer。然后我抓住了它的边界矩形。

所以上面的计算行会变成:

var bgrect = document.getElementsByClassName('gridlayer')[0].getBoundingClientRect();
var x = ((e.x - bgrect['x']) / (bgrect['width'])) * (myPlot.layout.xaxis.range[1] - myPlot.layout.xaxis.range[0]) + myPlot.layout.xaxis.range[0];
var y = ((e.y - bgrect['y']) / (bgrect['height'])) * (myPlot.layout.yaxis.range[0] - myPlot.layout.yaxis.range[1]) + myPlot.layout.yaxis.range[1];

如果您想使用最新版本的 plotly,还需要进行一项额外更改。 d3 不再嵌入 plotly,因此有必要从 CDN 获取 d3(我发现适用于此的最新版本是 v5)。

<script src="https://cdn.plot.ly/plotly-2.11.0.min.js"></script>
<script src="//d3js.org/d3.v5.min.js"></script>

在脚本中,您只需在根目录中引用 d3 即可:

d3.select(".plotly").on('click', function(d, i) {
var e = d3.event;

我将之前发布的代码笔示例修改为这个新方法https://codepen.io/jranalli/pen/eYyVVgr