以下代码用于使用滑块更改 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>
需要为每个滑块步骤完全重新绘制热图,这特别需要时间,因为点数(500k)。
但是,正如评论中所讨论的那样,似乎没有平滑算法(
zsmooth:false
)比有(zsmooth:'best'
或zsmooth:'fast'
)需要更长的时间,这是不合逻辑的:它应该是由于插值成本,另一种方式。查看代码,我可以确认存在可以/应该解决的性能问题(和错误)。
在 PR 解决问题之前,您可以使用一个变通解决方案,其中包括设置:
zsmooth:'fast'
为了受益于(当前)最快的绘图方法。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>
我关于提高 Plotly.js 热图中色阶滑块响应能力的建议:
将滑块步骤的“restyle”替换为“animate”方法。 创建自定义帧数组来存储滑块帧。 将持续时间和过渡时间设置为 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>
完全归功于 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" />