javascript 如何有一个更快的渲染,当移动一个滑块的色标范围,与绘图?

tf7tbtn2  于 2023-04-28  发布在  Java
关注(0)|答案(4)|浏览(143)

下面的代码用于使用滑块更改Plotly热图的色标的“min”。
但它很慢:我们有一个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>
fxnxkyjh

fxnxkyjh1#

完全归功于EricLavault的伟大发现和his answer,这给出了一个很好的解决方案,直到Plotly。JS热图代码得到改进。
下面是一个解决bug的方法,供将来参考:使用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" />
qeeaahzv

qeeaahzv2#

热图需要为每个滑块步骤完全重新绘制,这特别需要时间,因为点的数量(500k)。
然而,如评论中所讨论的,似乎没有平滑算法(zsmooth:false)时比有平滑算法(zsmooth:'best'zsmooth:'fast')时花费的时间更长,这是不符合逻辑的:由于插值成本,则应该相反。通过查看代码,我可以确认存在可以解决的性能问题。
在PR修复问题之前,您可以使用一个解决方案,其中包括设置:

  1. zsmooth:'fast',以便受益于(当前)最快的绘图方法。
  2. image-rendering: pixelated以防止浏览器执行平滑。
    当然,因为这太容易了,你会遇到一个bug,那就是在使用zsmooth:'fast'时,高分辨率的热图会被“截断”(这个问题在版本2中已经修复了)。为了避免这个问题,我们需要在布局中设置明确的宽度,高度和边距。
    注意:关于图大小,如果您想给予用户一个机会正确地看到热图,则设置明确的宽度、高度和边距可能是必要的。显然,除非定义了特定(缩放)范围,否则每个块至少一个像素,并且对于滑块,每个步长也是一个像素(最后,分辨率本身可能是一个问题)。
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>
jxct1oxe

jxct1oxe3#

我的建议,以提高响应的色标滑块在一个Plotly。js热图:
对于滑块步骤,将“restyle”替换为“animate”方法。创建自定义帧阵列来存储滑块帧。将持续时间和过渡时间设置为0以进行即时更新。使用单独的函数根据滑块值更新色标。

wgmfuz8q

wgmfuz8q4#

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>

相关问题