javascript 使用Plotly.JS在彼此顶部显示不透明的两个热图

iaqfqrcu  于 2023-02-07  发布在  Java
关注(0)|答案(1)|浏览(161)

我正在尝试将this answer移植到一个100%的Plotly.JS解决方案。TL;DR:如何使用Plotly.JS(非Python)在每个热图顶部使用不透明度滑块创建两个热图?
解的开始,但是如何添加第二个痕迹呢?

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" }];
const steps = [];
for (let i = 0; i <= 100; i++)
  steps.push({ label: i + "%", execute: true, method: "restyle", args: [{ opacity: i / 100 }] });
const layout = { sliders: [{ name: "slider", steps: steps, active: 100 }] };
Plotly.newPlot("graph", data, layout);
<script src="https://cdn.plot.ly/plotly-2.16.2.min.js"></script>
<div id="graph"></div>

供参考:原始Python解决方案:

from PIL import Image
import plotly.graph_objects as go
import numpy as np
import scipy.misc

imgA = scipy.misc.face()
imgB = Image.fromarray(np.random.random(imgA.shape[:2])*255).convert('RGB')

fig = go.Figure([
    go.Image(name='raccoon', z=imgA, opacity=1), # trace 0
    go.Image(name='noise', z=imgB, opacity=0.5)  # trace 1
])

slider = {
    'active': 50,
    'currentvalue': {'prefix': 'Noise: '},
    'steps': [{
        'value': step/100,
        'label': f'{step}%',
        'visible': True,
        'execute': True,
        'method': 'restyle',
        'args': [{'opacity': step/100}, [1]]     # apply to trace [1] only
    } for step in range(101)]
}

fig.update_layout(sliders=[slider])
fig.show(renderer='browser')
relj7zay

relj7zay1#

第二条轨迹也进入data数组,需要注意的是索引很重要:索引1处的迹线被绘制在索引0处的迹线之上,等等。
对于slider配置,它应该和python中的一样:每一步变化触发具有相同自变量(即,Plotly.restyle(graphDiv, ...args))的相同“restyle”方法,即,具有args,使得方法调用匹配签名:

Plotly.restyle(graphDiv, update [, traceIndices])

现在,最重要的事情是滑块应该指向 * 哪个trace*(traceIndices),也就是说,对于显式命名的跟踪,是哪个 index 或哪个 name(如果我没记错的话,默认值是 all),但在Python和Javascript之间也没有变化。
下面是一个完整的示例(在codepen.io上试用):

// Random z data
const t = {length: 400};
const z0 = Array.from(t, () => Array.from(t, () => Math.floor(Math.random() * 100)));
const z1 = Array.from(t, () => Array.from(t, () => Math.floor(Math.random() * 100)));

// Initial opacity for the trace 'above' 
const op_init = 0.5;

const data = [
  // Nb. Trace 1 drawn on top of trace 0
  {type: 'heatmap', z: z0, colorscale: 'Greys'},                    // trace 0
  {type: 'heatmap', z: z1, colorscale: 'Cividis', opacity: op_init} // trace 1
];

// Steps for the opacity slider
const steps = [];
const n_steps = 100; // number of steps above step 0
for (let i = 0; i <= n_steps; i++) {
  steps.push({
    label: i + '%',
    execute: true,
    method: 'restyle',
    args: [{
      opacity: i/n_steps
    }, [1]] // <- Nb. this applies only to trace 1
  });
}

const layout = {
  width: 600,
  sliders: [{
    steps: steps,
    active: Math.round(op_init * n_steps), // slider default matches op_init 
    pad: {t: 30},
    currentvalue: {prefix: 'opacity: '}
  }]
};

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

相关问题