sgratzl/chartjs-chart-graph

Edge line styles

lachdoug opened this issue · 4 comments

Hi sgratzl

I very much appreciate the work that you do to make this package available.

I have a question about how to apply style to edge lines.

Using edgeLineBorderWidth, edgeLineBorderDash and edgeLineBorderColor, I can apply style successfully when the number of edges equals the number of nodes.

When I add more edges than nodes, the additional nodes take the style of the first edge. For example, this image shows a test graph where each edge line should have unique style, but the last two edges have the same style as the first:
image

const data = [{},{},{},{}];

const edges = [
  {source: 1, target: 0},
  {source: 2, target: 0},
  {source: 2, target: 1},
  {source: 3, target: 1},
  {source: 3, target: 0},
  {source: 3, target: 2},
];

const widths = [ 2, 5, 10, 15, 20, 25 ];
const dashes = [ [2,2], [5,5] ,[10,10] ,[15,15] ,[20,20] ,[25,25] ];
const colors = [ 'blue', 'red', 'green', 'purple', 'pink', 'yellow' ]
      
new Chart(document.querySelector("canvas").getContext("2d"), {
  type: 'forceDirectedGraph',
  data: {
    datasets: [{
      pointRadius: 20,
      data: data,
      edges: edges,
      edgeLineBorderWidth: ctx => widths[ctx.index],
      edgeLineBorderDash: ctx => dashes[ctx.index],
      edgeLineBorderColor: ctx => colors[ctx.index]
    }]
  },
  options: {
    scales: {
      x: { min: -1.5, max: 1.5 },
      y: { min: -1.5, max: 1.5 }
    },
    plugins: { legend: { display: false } }
  }
});

Following the example in docs/examples/tree.ts, I've also tried with:

      edgeLineBorderWidth: ctx => widths[ctx.dataIndex],
      edgeLineBorderDash: ctx => dashes[ctx.dataIndex],
      edgeLineBorderColor: ctx => colors[ctx.dataIndex]

Using:

  • chart.js v4.4.0
  • chartjs-chart-graph v4.2.3

Is this expected behavior, am I doing something wrong, or is this a bug? Here is the codepen: https://codepen.io/lachdoug/pen/gOZRORG

Thank you.

After looking at the source code I noted that the functions for edgeLineBorderWidth, edgeLineBorderDash and edgeLineBorderColor are called with arguments (_context, _subProxy || receiver) and that _subProxy.edges returns values for source and target. This led me to try:

// added this lookup function to the codepen
const findEdgeIndex = (subProxy) => {
  const source = subProxy.edges.source
  const target = subProxy.edges.target
  return edges.findIndex(
    edge => edge.source == source && edge.target == target
  )
}

// then changed the dataset to
      edgeLineBorderWidth: (ctx, subProxy) => widths[findEdgeIndex(subProxy)],
      edgeLineBorderDash: (ctx, subProxy) => dashes[findEdgeIndex(subProxy)],
      edgeLineBorderColor: (ctx, subProxy) => colors[findEdgeIndex(subProxy)]

That gave the same result, in that it doesn't work for the last two edges. The source and target values on subProxy.edges are correct for the first four edges, but then for the last two edges the values revert to the values for the first edge.

Here's a second codepen: https://codepen.io/lachdoug/pen/rNowawW

I've done some more research and I think the problem has to do with chart.js. I can't see an easy way to make chartjs-chart-graph iterate over edges rather than nodes. I'm going to close this issue.

fixed with #85

Nice work! Thank you very much.