【问题标题】:Slow rendering of image + slider with Plotly JS使用 Plotly JS 缓慢渲染图像 + 滑块
【发布时间】:2022-11-27 02:49:28
【问题描述】:

渲染此图像/热图后,不应进行任何计算,并且移动滑块应该是即时的。相反,移动滑块是非常慢(每个位置之间滞后 1 秒),并使用最大 CPU %。

如何使用 Plotly JS 进行更快的滑块渲染?

var z = [], steps = [], i;
for (i = 0; i < 500; i++) 
    z.push(Array.from({length: 600}, () => Math.floor(Math.random() * 100)));  
for (i = 0; i < 100; i++)
    steps.push({ label: i, method: 'restyle', args: ['line.color', 'red']});
var data = [{z: z, colorscale: 'YlGnBu', type: 'heatmap'}];
var layout = {title: '', sliders: [{
    pad: {t: 5},
    len: 1,
    x: 0,
    currentvalue: {
      xanchor: 'right',
      prefix: 'i: ',
      font: {
        color: '#888',
        size: 20
      }
    },
    steps: steps
  }]};
Plotly.newPlot('myDiv', data, layout);
<script src="https://cdn.plot.ly/plotly-2.16.2.min.js"></script>
<div id="myDiv"></div>

【问题讨论】:

  • 想法:我们可以将滑块移动到一个单独的 div,没有 plot/graph 吗?我们将使用两个Plotly.newPlot,一个用于热图,另一个没有任何数据,只有滑块。这可能吗?我做不到后者。
  • 这是因为您将 method: 'restyle' 与错误的 args 一起使用(没有线,但它似乎和有很多线一样慢,我怀疑它默认为重新设置 z 数据点的样式),这是减缓。但是你想做什么?它与不透明度问题有关吗?
  • @EricLavault 是的,一个滑块将更改(此热图的)不透明度,第二个滑块将修改一个参数,该参数将在每个“onchange”事件上通知服务器(使用 AJAX / fetch)。我正在寻找仅 JS 的解决方案(这部分没有 Python)。我正在开放赏金,因为我对实现它的标准 plotly.js 方法感到好奇。

标签: javascript performance plotly plotly.js


【解决方案1】:

这是因为您将 method: 'restyle' 与错误的 args 一起使用,即。 ['line.color', 'red'] 语法不正确并且没有行,所以我猜 Plotly(不知道要重新调整样式)只是在滑块移动时重新绘制整个图,这很慢。

基本上,您可以在 javascript 和 python 中使用相同的滑块配置来完成相同的任务(最终将使用相同的 Plotly.js 滑块组件)。

例如,可以根据滑块的位置设置图像的不透明度,但要立即应用更改,需要在滑块的 steps 配置中设置正确的 methodargs,完全按照说明在这个post 中:

steps.push({
  label: i,
  execute: true,
  method: 'restyle',
  args: [{opacity: i/100}]
});

这是一个包含两个滑块的完整示例:一个更改热图的不透明度,另一个不触及绘图但仅触发特定处理程序:

const z = [];
for (let i=0; i<500; i++) {
  z.push(Array.from({length: 600}, () => Math.floor(Math.random() * 100)));
}

const data = [{z: z, colorscale: 'YlGnBu', type: 'heatmap'}];

// Steps for the heatmap opacity slider
const opacity_steps = [];
for (let i = 0; i <= 100; i++) {
  opacity_steps.push({
    label: i + '%',
    execute: true,
    method: 'restyle',
    args: [{opacity: i/100}]
  });
}

// Steps for the custom slider
const custom_steps = [];
for (let i = 50; i <= 200; i++) {
  custom_steps.push({
    label: i,
    execute: false,
    method: 'skip',
  });
}

const layout = {
  title: '',
  sliders: [{
    name: 'opacity_slider',
    steps: opacity_steps,
    active: 100,
    pad: {t: 30},
    currentvalue: {prefix: 'opacity: '}
  }, {
    name: 'custom_slider',
    steps: custom_steps,
    pad: {t: 120},
    currentvalue: {prefix: 'i: '}
  }]
};

Plotly.newPlot('graph', data, layout);

// Retrieve the graph div
const gd = document.getElementById('graph');

// Attach 'plotly_sliderchange' event listener to it (note that we can't specify
// which slider the handler is taking care of using a secondary selector)
gd.on('plotly_sliderchange', function(event) {
  // ... so we have to distinguish between the two sliders here.
  if (event.slider.name != 'custom_slider')
    return;

  const slider = event.slider;       // the slider emitting the event (object)
  const step = event.step;           // the currently active step (object)
  const prev = event.previousActive; // index of the previously active step

  const value = step.value;          // captain obvious was here
  const index = step._index;         // index of the current step

  // ...
});
<script src="https://cdn.plot.ly/plotly-2.16.2.min.js"></script>
<div id="graph"></div>

【讨论】:

    猜你喜欢
    • 2022-01-25
    • 2013-11-25
    • 2018-01-22
    • 2021-05-19
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多