plotly js: how to run my javascript ONLY after plot image is loaded

最后都变了- 提交于 2019-12-01 14:49:04

问题


When using a plotly graph of any sort with the Javascript API (plotly.js, not plotly-nodejs), how can I run some javascript ONLY after the graph has loaded? I'm looking for the mechanism in the plotly javascript API that, for example, does the same thing that 'addListenerOnce', in conjunction with 'tilesloaded' or 'ready', do when using the Google Maps API.

For example, let's say I want to simply display an alert immediately after rendering the example shown at https://plot.ly/~PlotBot/685, for which the html and js code can be seen at https://plot.ly/~PlotBot/685.js.

There are many reasons to do this, but the one I am faced with now is using wkhtml2pdf, which must wait for the page to be rendered before displaying (see wkhtmltopdf javascript delay) (Yes, I know I can use --javascript-delay with wkhtml2pdf, but hardcoding a fixed amount of time and hoping that your program waited long enough for its next steps to succeed is not the solution I'm looking for-- and besides, that approach is specific to wkhtml2pdf and does not answer the general question).

Prefer a browser-independent solution but at the least, need one that works on Chrome


回答1:


Using the promise, as mentioned in the comments above, is the correct solution. However, the promise fires before the first animation frame is done rendering. As a workaround, you can subscribe to the promise and then wait for the animation frame to finish, using requestAnimationFrame.

EDIT: A single animation frame was sufficient for Firefox, but not Chrome. So I'm editing to use a pair of animation frames, which appears to fix the issue in Chrome, and should continue to work in Firefox. This of course is just a workaround for an issue in Plotly, as the promise should not resolve until the plot has actually rendered.

Here's an example:

var trace1 = {
  z: [[8.83, 8.89, 8.81, 8.87, 8.9, 8.87], [8.89, 8.94, 8.85, 8.94, 8.96, 8.92], [8.84, 8.9, 8.82, 8.92, 8.93, 8.91], [8.79, 8.85, 8.79, 8.9, 8.94, 8.92], [8.79, 8.88, 8.81, 8.9, 8.95, 8.92], [8.8, 8.82, 8.78, 8.91, 8.94, 8.92], [8.75, 8.78, 8.77, 8.91, 8.95, 8.92], [8.8, 8.8, 8.77, 8.91, 8.95, 8.94], [8.74, 8.81, 8.76, 8.93, 8.98, 8.99], [8.89, 8.99, 8.92, 9.1, 9.13, 9.11], [8.97, 8.97, 8.91, 9.09, 9.11, 9.11], [9.04, 9.08, 9.05, 9.25, 9.28, 9.27], [9, 9.01, 9, 9.2, 9.23, 9.2], [8.99, 8.99, 8.98, 9.18, 9.2, 9.19], [8.93, 8.97, 8.97, 9.18, 9.2, 9.18]], 
  colorbar: {
    xpad: 0, 
    ypad: 0
  }, 
  showscale: false, 
  type: "surface", 
  uid: "3f95e8", 
  zmax: 9.28, 
  zmin: 8.74
};
var trace2 = {
  z: [[9.83, 9.89, 9.81, 9.87, 9.9, 9.87], [9.89, 9.94, 9.85, 9.94, 9.96, 9.92], [9.84, 9.9, 9.82, 9.92, 9.93, 9.91], [9.79, 9.85, 9.79, 9.9, 9.94, 9.92], [9.79, 9.88, 9.81, 9.9, 9.95, 9.92], [9.8, 9.82, 9.78, 9.91, 9.94, 9.92], [9.75, 9.78, 9.77, 9.91, 9.95, 9.92], [9.8, 9.8, 9.77, 9.91, 9.95, 9.94], [9.74, 9.81, 9.76, 9.93, 9.98, 9.99], [9.89, 9.99, 9.92, 10.1, 10.13, 10.11], [9.97, 9.97, 9.91, 10.09, 10.11, 10.11], [10.04, 10.08, 10.05, 10.25, 10.28, 10.27], [10, 10.01, 10, 10.2, 10.23, 10.2], [9.99, 9.99, 9.98, 10.18, 10.2, 10.19], [9.93, 9.97, 9.97, 10.18, 10.2, 10.18]], 
  opacity: 0.9, 
  showscale: false, 
  type: "surface", 
  uid: "443a24", 
  zmax: 10.28, 
  zmin: 9.74
};
var trace3 = {
  z: [[7.83, 7.89, 7.81, 7.87, 7.9, 7.87], [7.89, 7.94, 7.85, 7.94, 7.96, 7.92], [7.84, 7.9, 7.82, 7.92, 7.93, 7.91], [7.79, 7.85, 7.79, 7.9, 7.94, 7.92], [7.79, 7.88, 7.81, 7.9, 7.95, 7.92], [7.8, 7.82, 7.78, 7.91, 7.94, 7.92], [7.75, 7.78, 7.77, 7.91, 7.95, 7.92], [7.8, 7.8, 7.77, 7.91, 7.95, 7.94], [7.74, 7.81, 7.76, 7.93, 7.98, 7.99], [7.89, 7.99, 7.92, 8.1, 8.13, 8.11], [7.97, 7.97, 7.91, 8.09, 8.11, 8.11], [8.04, 8.08, 8.05, 8.25, 8.28, 8.27], [8, 8.01, 8, 8.2, 8.23, 8.2], [7.99, 7.99, 7.98, 8.18, 8.2, 8.19], [7.93, 7.97, 7.97, 8.18, 8.2, 8.18]], 
  opacity: 0.9, 
  showscale: false, 
  type: "surface", 
  uid: "47cf99", 
  zmax: 8.28, 
  zmin: 7.74
};
var data = [trace1, trace2, trace3];
var layout = {
  autosize: false, 
  height: 200, 
  margin: {
    r: 0, 
    t: 0, 
    autoexpand: false, 
    b: 0, 
    l: 0
  }, 
  scene: {
    aspectmode: "manual", 
    aspectratio: {
      x: 1, 
      y: 1, 
      z: 1
    }, 
    camera: {
      center: {
        x: 0, 
        y: 0, 
        z: 0
      }, 
      eye: {
        x: 1.59999582495, 
        y: 1.57131061558, 
        z: 0.970117065684
      }, 
      up: {
        x: 0, 
        y: 0, 
        z: 1
      }
    }
  }, 
  width: 650
};
Plotly.plot('plotly-div', data, layout).then(function() {
  window.requestAnimationFrame(function() {
    window.requestAnimationFrame(function() {
      window.alert('Your plot is done.');
    });
  });
});
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="plotly-div"></div>



回答2:


on this page: https://plot.ly/javascript/getting-started/ under

Start plotting!

You are asked to create a div with an id.

By adding onload as a attribute (or in javascript)

You get this: <div id="tester" onload="myFunction()" style="width:600px;height:250px;"></div>

"myFunction" can contain the code you want execute after loading the image.

http://www.w3schools.com/jsref/event_onload.asp



来源:https://stackoverflow.com/questions/34315834/plotly-js-how-to-run-my-javascript-only-after-plot-image-is-loaded

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!