如何使用 Plotly.js 同步多个图表的缩放级别?

RMS*_*RMS 6 javascript charts plotly

我使用 Plotly.js 创建了 3 个时间序列图,并且我希望保持缩放级别/平移同步,因此如果用户缩放/平移 3 个图中的任何一个,则其他 2 个得到更新。

现在我在事件的第一个图表上设置了一个事件处理程序plotly_relayout。事件处理程序使用传入的事件数据调用Plotly.relayout其他两个图表。

有谁知道如何识别哪个图首先发出plotly_relayout事件,这样它就不会陷入处理自己事件的循环中?或者也许有更好的方法来处理保持多个图表之间的缩放/平移同步?

见笔在Plotly.js图表链接放大活动由不宁头脑工作室(@restlessmindsstudio)上CodePen

Ale*_*lex 5

正如 Ashish Rathi 注意到的,上述解决方案有一个错误 - 当您尝试按下某些按钮时,代码执行进入无限循环。解决方案是检查自己的重新布局处理程序中的“ed”变量,如果它没有属性 - 只是退出。看起来在某些情况下,Plotly 发送带有包含更新的空对象的plotly_relayout 事件只是为了好玩 - 可能是某种错误。

就我而言,我不想将 Y 缩放从一个图传播到另一个图 - 因此我准备了一个单独的结构,其中仅包含我想要传播的那些属性。

var myDiv = document.getElementById("myDiv");
var myDiv2 = document.getElementById("myDiv2");
var myDiv3 = document.getElementById("myDiv3");
var startTime = new Date().getTime();
var timeStep = 60000;
var myDivMax = 70;
var myDiv2Max = 9000;
var myDiv3Max = 500;

var d3 = Plotly.d3,
  N = 40,
  x = d3.range(N).map(() => {
    return new Date((startTime += timeStep));
  }),
  y = d3.range(N).map(() => Math.random() * myDivMax),
  data = [{ x: x, y: y }];
var layout = {
  height: 200,
  margin: { l: 45, t: 5, r: 45, b: 45 },
  xaxis: {
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  },
  yaxis: {
    fixedrange: true,
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  }
};
var layout2 = {
  height: 200,
  margin: { l: 45, t: 5, r: 45, b: 45 },
  xaxis: {
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  },
  yaxis: {
    fixedrange: true,
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  }
};
var layout3 = {
  height: 200,
  margin: { l: 45, t: 5, r: 45, b: 45 },
  xaxis: {
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  },
  yaxis: {
    fixedrange: true,
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  }
};

Plotly.plot(myDiv, data, layout);
var data2 = [{ x: x, y: d3.range(N).map(() => Math.random() * myDiv2Max) }];
Plotly.plot(myDiv2, data2, layout2);
var data3 = [{ x: x, y: d3.range(N).map(() => Math.random() * myDiv3Max) }];
Plotly.plot(myDiv3, data3, layout3);

var divs = [myDiv, myDiv2, myDiv3];

function relayout(ed, divs) {
  if (Object.entries(ed).length === 0) {return;}
  divs.forEach((div, i) => {
    let x = div.layout.xaxis;
    if (ed["xaxis.autorange"] && x.autorange) return;
    if (x.range[0] != ed["xaxis.range[0]"] ||x.range[1] != ed["xaxis.range[1]"])
    {
      var update = {
      'xaxis.range[0]': ed["xaxis.range[0]"],
      'xaxis.range[1]': ed["xaxis.range[1]"],
      'xaxis.autorange': ed["xaxis.autorange"],
     };
     Plotly.relayout(div, update);
    }
  });
}

var plots = [myDiv, myDiv2, myDiv3];
plots.forEach(div => {
  div.on("plotly_relayout", function(ed) {
    relayout(ed, divs);
  });
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<h2>Resize any chart, the others will get the same zoom level applied</h2>
<div id="myDiv"></div>
<div id="myDiv2"></div>
<div id="myDiv3"></div>
Run Code Online (Sandbox Code Playgroud)


RMS*_*RMS 3

我在这里复制 @ChrisG 的评论以给予他信任并显示我的问题的答案:

找到了更好的解决方案:https://codepen.io/anon/pen/NXRpzW?editors =1010

var myDiv = document.getElementById("myDiv");
var myDiv2 = document.getElementById("myDiv2");
var myDiv3 = document.getElementById("myDiv3");
var startTime = new Date().getTime();
var timeStep = 60000;
var myDivMax = 70;
var myDiv2Max = 9000;
var myDiv3Max = 500;

var d3 = Plotly.d3,
  N = 40,
  x = d3.range(N).map(() => {
    return new Date((startTime += timeStep));
  }),
  y = d3.range(N).map(() => Math.random() * myDivMax),
  data = [{ x: x, y: y }];
var layout = {
  height: 200,
  margin: { l: 45, t: 5, r: 45, b: 45 },
  xaxis: {
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  },
  yaxis: {
    fixedrange: true,
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  }
};
var layout2 = {
  height: 200,
  margin: { l: 45, t: 5, r: 45, b: 45 },
  xaxis: {
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  },
  yaxis: {
    fixedrange: true,
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  }
};
var layout3 = {
  height: 200,
  margin: { l: 45, t: 5, r: 45, b: 45 },
  xaxis: {
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  },
  yaxis: {
    fixedrange: true,
    tickfont: {
      size: 10,
      color: "#7f7f7f"
    }
  }
};

Plotly.plot(myDiv, data, layout);
var data2 = [{ x: x, y: d3.range(N).map(() => Math.random() * myDiv2Max) }];
Plotly.plot(myDiv2, data2, layout2);
var data3 = [{ x: x, y: d3.range(N).map(() => Math.random() * myDiv3Max) }];
Plotly.plot(myDiv3, data3, layout3);

var divs = [myDiv, myDiv2, myDiv3];

function relayout(ed, divs) {
  divs.forEach((div, i) => {
    let x = div.layout.xaxis;
    if (ed["xaxis.autorange"] && x.autorange) return;
    if (
      x.range[0] != ed["xaxis.range[0]"] ||
      x.range[1] != ed["xaxis.range[1]"]
    )
      Plotly.relayout(div, ed);
  });
}

var plots = [myDiv, myDiv2, myDiv3];
plots.forEach(div => {
  div.on("plotly_relayout", function(ed) {
    console.log(ed);
    relayout(ed, divs);
  });
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<h2>Resize any chart, the others will get the same zoom level applied</h2>
<div id="myDiv"></div>
<div id="myDiv2"></div>
<div id="myDiv3"></div>
Run Code Online (Sandbox Code Playgroud)