如何为Plotly.js中3D网络图的锥体设置不同颜色
解决Plotly.js 3D锥体独立着色问题
在Plotly.js中,单个cone trace默认共享颜色映射,直接设置color数组时需要正确配置才能让每个锥体显示不同颜色。以下是两种可行的解决方案:
方案1:单个trace内通过color数组指定独立颜色
直接在traceCone的color属性中传入RGB字符串数组,每个元素对应一个锥体的颜色:
var traceCone = { type: "cone", x: [0.5, 1.5, 2.5, 3.5], y: [0.5, 0.5, 0.5, 0.5], z: [0.5, 1.5, 2.5, 3.5], u: [1,1,1,1], v: [1,-1,1,-1], w: [1,1,1,1], sizemode: "absolute", sizeref: 0.5, // 为每个锥体指定不同的RGB颜色 color: ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)', 'rgb(255, 255, 0)'], showscale: false };
如果需要使用颜色渐变映射,可以保留colorscale并传入数值数组,每个数值会映射到colorscale对应的颜色区间:
var traceCone = { type: "cone", x: [0.5, 1.5, 2.5, 3.5], y: [0.5, 0.5, 0.5, 0.5], z: [0.5, 1.5, 2.5, 3.5], u: [1,1,1,1], v: [1,-1,1,-1], w: [1,1,1,1], sizemode: "absolute", sizeref: 0.5, color: [1, 2, 3, 4], // 数值数组对应每个锥体的颜色映射值 colorscale: [[0, 'rgb(255, 0, 0)'], [0.33, 'rgb(0, 255, 0)'], [0.66, 'rgb(0, 0, 255)'], [1, 'rgb(255, 255, 0)']], showscale: false };
方案2:为每个锥体创建独立的cone trace
如果需要对每个锥体做更精细的单独配置(比如不同大小、透明度),可以为每个锥体创建独立的cone trace:
// 定义所有锥体的配置参数 var coneConfigs = [ {x: 0.5, y: 0.5, z: 0.5, u:1, v:1, w:1, color: 'rgb(255, 0, 0)'}, {x: 1.5, y: 0.5, z: 1.5, u:1, v:-1, w:1, color: 'rgb(0, 255, 0)'}, {x: 2.5, y: 0.5, z: 2.5, u:1, v:1, w:1, color: 'rgb(0, 0, 255)'}, {x: 3.5, y: 0.5, z: 3.5, u:1, v:-1, w:1, color: 'rgb(255, 255, 0)'} ]; // 生成多个cone trace var coneTraces = coneConfigs.map(config => ({ type: "cone", x: [config.x], y: [config.y], z: [config.z], u: [config.u], v: [config.v], w: [config.w], sizemode: "absolute", sizeref: 0.5, color: config.color, showscale: false })); // 绘图时将所有trace传入 Plotly.newPlot('myDiv', [traceNodes, traceEdges, ...coneTraces], layout, { displayModeBar: false });
修改后的完整代码(方案1示例)
<html> <head> <script src="https://cdn.plot.ly/plotly-1.58.5.min.js"></script> <style> .graph-container { display: flex; justify-content: center; align-items: center; } .main-panel { width: 70%; float: left; } .side-panel { width: 30%; background-color: lightgray; min-height: 300px; overflow: auto; float: right; } </style> </head> <body> <div class="graph-container"> <div id="myDiv" class="main-panel"></div> <div id="lineGraph" class="side-panel"></div> </div> <script> var nodes = [ { x: 0, y: 0, z: 0, value: [1, 2, 3] }, { x: 1, y: 1, z: 1, value: [4, 5, 6] }, { x: 2, y: 0, z: 2, value: [7, 8, 9] }, { x: 3, y: 1, z: 3, value: [10, 11, 12] }, { x: 4, y: 0, z: 4, value: [13, 14, 15] } ]; var edges = [ { source: 0, target: 1 }, { source: 1, target: 2 }, { source: 2, target: 3 }, { source: 3, target: 4 } ]; var x = []; var y = []; var z = []; for (var i = 0; i < nodes.length; i++) { x.push(nodes[i].x); y.push(nodes[i].y); z.push(nodes[i].z); } const edge_x = []; const edge_y = []; const edge_z = []; for (var i = 0; i < edges.length; i++) { const a = nodes[edges[i].source]; const b = nodes[edges[i].target]; edge_x.push(a.x, b.x, null); edge_y.push(a.y, b.y, null); edge_z.push(a.z, b.z, null); } var traceNodes = { x: x, y: y, z: z, mode: 'markers', text: [0, 1, 2, 3, 4], marker:{color: [1,2,3,4,5],colorscale: [[0, 'rgb(255, 0, 0)'], [1, 'rgb(0, 0, 255)']], showscale: true, size: 12}, hoverinfo: 'text', hoverlabel: { bgcolor: 'white' }, customdata: nodes.map(function(node) { if (node.value !== undefined) return node.value; }), type: 'scatter3d' }; var traceEdges = { x: edge_x, y: edge_y, z: edge_z, line: { color: [4,1,4,1,4,1], colorscale: [[0, 'rgb(255, 0, 0)'], [1, 'rgb(0, 0, 255)']], showscale: true, width: 5 }, type: 'scatter3d', mode: 'lines', opacity: 2.8 }; var layout = { margin: { l: 0, r: 0, b: 0, t: 0 } }; // 修改后的锥体配置,每个锥体使用不同颜色 var traceCone = { type: "cone", x: [0.5, 1.5, 2.5, 3.5], y: [0.5, 0.5, 0.5, 0.5], z: [0.5, 1.5, 2.5, 3.5], u: [1,1,1,1], v: [1,-1,1,-1], w: [1,1,1,1], sizemode: "absolute", sizeref: 0.5, color: ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)', 'rgb(255, 255, 0)'], showscale: false }; Plotly.newPlot('myDiv', [traceNodes, traceEdges,traceCone],layout, { displayModeBar: false }); const ymax = Math.max(...nodes.map(n => n.value).flat()); document.getElementById('myDiv').on('plotly_click', function(data){ var nodeIndex = data.points[0].pointNumber; var values = nodes[nodeIndex].value; var update = { marker: { color: [1,2,3,4,5],colorscale: [[0, 'rgb(255, 0, 0)'], [1, 'rgb(0, 0, 255)']], showscale: true, size: 12} }; update.marker.color[nodeIndex] = 'blue'; setTimeout(function() { Plotly.restyle('myDiv', update); }, 50); Plotly.newPlot('lineGraph', [{ type: 'scatter', mode: 'lines', x: [0, 1, 2], y: values }], { margin: { t: 0 }, yaxis: {autorange: false, range: [0, ymax + 1]} }); }); </script> </body> </html>
内容的提问来源于stack exchange,提问作者LaluBadmaash
相关产品推荐
相关产品推荐

