LaluBadmaash
LaluBadmaash

Reputation: 1

How to give different colors to the cones in plotly.js

`

<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',
        // marker: { size: 12, color: 'red' },
        // marker: { size: 12, color: Array.from({length: nodes.length}, () => 'red') },
        text: [0, 1, 2, 3, 4],
        // add the color gradient to the nodes from red to blue
        // marker: { size: 12, color: Array.from({length: nodes.length}, () => 'red'), colorscale: 'Viridis'},
        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,
        //add the color gradient to the lines from red to blue
        // line: { color: Array.from({length: edge_x.length}, () => 'red'), width: 5, colorscale: 'Viridis'},
        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',
        // line: { color: 'red', width: 2, arrow: {size: 50, color: 'black', end:1}},
        // line: { color: 'red', width: 2, shape: 'spline', arrow: {size: 500, color: 'black', end:1}},
        //add color gradient to the lines
        // line: {  width: 2, shape: 'spline', arrow: {size: 500, color: 'black', end:1}, colorscale: 'Viridis'},
        opacity: 2.8
        //add cones shape to the end of the lines
        


      };

      var layout = {
        margin: { l: 0, r: 0, b: 0, t: 0 }
      };

      // var traceCone = {
      //   type: "cone",
      //   x: [1], y: [1], z: [1],
      //   u: [1], v: [1], w: [0]
      // };

      //add the cones shape at the middle of the lines and they are pointing to the end of the lines
      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],
        //set the size of the cones
        sizemode: "absolute",
        sizeref: 0.5,
        // give color to cone which have co-oridnates (0.5,0.5,0.5)
        colorscale: [[0, 'rgb(255, 0, 0)'], [1, 'rgb(0, 0, 255)']],
        // color: [1,2,3,4], // color array
        // colorscale: 'Viridis',
        showscale: false
        
        // colorscale: 'Viridis',
        // color: [1,4,1,1,4,1],

        // showscale: false,
      };
      

      Plotly.newPlot('myDiv', [traceNodes, traceEdges,traceCone],layout, { displayModeBar: false });

      // max y value for the line plot
      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;

      //change the color of the clicked node to blue and when clicked on another node, change the color of the previous node to red
      var update = {
        //give the color of the nodes to the initial color
        // marker: { color: Array.from({length: nodes.length}, () => 'red') }
        //give the color of the nodes to the color gradient
        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>

The code above shows how to display a 3D network graph , and cones were used as an arrow of the edge.Basically we wanted to give different colors to the cones,but its not working... Please help us to way out of this problem. So,the code that I have shown ,assign same color to all the cones (which I dont want), is there any way out?

Upvotes: 0

Views: 383

Answers (1)

EricLavault
EricLavault

Reputation: 16035

Unlike scatter traces, cone traces don't have a color property where you can specify an array of numbers that are mapped to a color scale. You can only define what the colorscale is, and its bounds in the color space using cmin and cmax.

The thing (number) that determines the color of a cone is its u/v/w norm in the vector field, and it seems that it's not possible to decide arbitrarily - regardless of that norm - how each cone should be colored.

If I'm not wrong the u/v/w norm is computed as follows :

const norm = Math.sqrt(u**2 + v**2 + w**2);

In your example, all cones are assigned the same color because they all have the same norm, which is √3. If you try to assign different u/v/w values, it should change accordingly.

Upvotes: 1

Related Questions