如何使用 Plotly 移动色标范围的滑块时进行更快的渲染?

问题描述 投票:0回答:4

以下代码用于使用滑块更改 Plotly 热图色标的“最小值”。

但是速度很慢:拖动滑块时我们有 1 fps 的移动。

用“heatmapgl”替换“heatmap”等解决方案并不能真正解决问题(它可能会提高到 2 fps)。

如何使用滑块更灵敏/更快地更改色标?

对于许多应用程序,能够“实时”(超过 10 fps)看到色标变化的结果是至关重要的,并且可以使用 Matplotlib 等来做到这一点

如何在 Plotly JS 中获得相同的行为?

var z = Array.from({length: 500}, () => Array.from({length: 1000}, () => Math.floor(Math.random() * 500)));  
var steps = [], i;
for (i = 0; i < 500; i++)
    steps.push({label: i, method: 'restyle', args: ['zmin', i]});
Plotly.newPlot('myDiv',  [{z: z, colorscale: 'Jet', type: 'heatmap'}], {sliders: [{steps: steps}]});
<script src="https://cdn.plot.ly/plotly-2.16.2.min.js"></script>
<div id="myDiv"></div>

javascript plotly visualization plotly-dash plotly.js
4个回答
1
投票

需要为每个滑块步骤完全重新绘制热图,这特别需要时间,因为点数(500k)。

但是,正如评论中所讨论的那样,似乎没有平滑算法(

zsmooth:false
)比有(
zsmooth:'best'
zsmooth:'fast'
)需要更长的时间,这是不合逻辑的:它应该是由于插值成本,另一种方式。查看代码,我可以确认存在可以/应该解决的性能问题(和错误)。

在 PR 解决问题之前,您可以使用一个变通解决方案,其中包括设置:

  1. zsmooth:'fast'
    为了受益于(当前)最快的绘图方法。
  2. image-rendering: pixelated
    以防止浏览器进行平滑操作。

当然,因为这太容易了,你会遇到第二个错误,即高分辨率热图在使用时以某种方式被“截断”

zsmooth:'fast'
(一些像素没有被绘制,因为它们被认为是在屏幕外).为了规避这一点,我们需要在布局中设置明确的宽度、高度和边距。

铌。关于绘图大小,如果您想让用户有机会正确查看热图,则无论如何这是必需的,即。除非定义了特定的(缩放)范围,否则每块砖至少一个像素,对于滑块以及每步一个像素(最后,分辨率本身可能是一个问题)。

var z = Array.from({length: 500}, () => Array.from({length: 1000}, () => Math.floor(Math.random() * 500)));  
var steps = [], i;

for (i = 0; i < 500; i++)
    steps.push({label: i, method: 'restyle', args: ['zmin', i]});

const data = [{
  z: z, 
  colorscale: 'Jet', 
  type: 'heatmap', 
  zsmooth: 'fast'
}];

const layout = {
  sliders: [{steps: steps}],
  width: 1200,
  height: 650,
  margin: {
    t: 40,
    b: 110,
    l: 90,
    r: 110
  }
};

Plotly.newPlot('myDiv', data, layout);
.subplot.xy .heatmaplayer image {
  image-rendering: pixelated;  
}
<script src="https://cdn.plot.ly/plotly-2.16.2.min.js"></script>
<div id="myDiv"></div>


0
投票

我关于提高 Plotly.js 热图中色阶滑块响应能力的建议:

将滑块步骤的“restyle”替换为“animate”方法。 创建自定义帧数组来存储滑块帧。 将持续时间和过渡时间设置为 0 以进行即时更新。 使用单独的函数根据滑块值更新色标。


0
投票

var z = Array.from({length: 500}, () => Array.from({length: 1000}, () => Math.floor(Math.random() * 500)));
var steps = [], i;
for (i = 0; i < 500; i++)
    steps.push({label: i, method: 'restyle', args: ['zmin', i]});

var myPlot = Plotly.newPlot('myDiv', [{z: z, colorscale: 'Jet', type: 'heatmap'}], {sliders: [{steps: steps}]});

function slider(func, w) {
  let timeElasped;
  return function executor(...args) {
    const l = () => {
      clearTimeout(timeElasped);
      func(...args);
    };
    clearTimeout(timeElasped);
    timeElasped = setTimeout(l, w);
  };
}

var updateZ = function(z) {
  Plotly.restyle('myDiv', 'zmin', z);
}

var sliderUpdateZ = slider(updateZ, 50);

myPlot.on('plotly_sliderchange', function(e){
  sliderUpdateZ(e.step.value);
});
<script src="https://cdn.plot.ly/plotly-2.16.2.min.js"></script>
<div id="myDiv"></div>


0
投票

完全归功于 EricLavault 的伟大发现和他的回答,它提供了一个很好的解决方案,直到 Plotly.JS 热图代码得到改进。

为了将来参考,这是另一种规避错误的解决方法:使用 HTML 本机滑块 (

<input type="range">
) 而不是 Plotly 滑块。对我来说,他的答案每秒帧数又提高了至少 2 倍。

var z = Array.from({length: 500}, () => Array.from({length: 1000}, () => Math.floor(Math.random() * 500)));  

const data = [{
  z: z, 
  colorscale: 'Jet', 
  type: 'heatmap', 
  zsmooth: 'fast'
}];

const layout = {
  width: 1200,
  height: 650,
  margin: {
    t: 40,
    b: 110,
    l: 90,
    r: 110
  }
};

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

document.getElementById("slider").oninput = (e) => {
    Plotly.restyle('myDiv', { zmin: e.target.value });
};
.subplot.xy .heatmaplayer image { image-rendering: pixelated; }
input { width: 100%; }
<script src="https://cdn.plot.ly/plotly-2.16.2.min.js"></script>
<div id="myDiv"></div>
<input type="range" id="slider" min="0" max="500" />

© www.soinside.com 2019 - 2024. All rights reserved.