Home > Software engineering >  Chart JS - Group Array Results on y axis
Chart JS - Group Array Results on y axis

Time:01-26

I think I am close to solving this but I am missing something critical. I have an array of "new" items that I am trying to plot on a chart to indicate how old they are. I can get the chart to load and plot the data but like items are not grouping onto the same line. Is there a way I can force the chart to put like types onto the same axis line in the chart? i.e. the 2 SAFE AE results load onto the same line? Any guidance would be appreciated!

var whatsNewArray = [{
    "type": "EAC",
    "age": -16
  },
  {
    "type": "EAC",
    "age": -58
  },
  {
    "type": "DSCC",
    "age": -36
  },
  {
    "type": "SAFE AE",
    "age": -95
  },
  {
    "type": "SAFE AE",
    "age": -94
  }
]

  new Chart(document.getElementById("myWHATSNEWChart"), {
    type: 'scatter',
    data: {
      datasets: [{
        data: whatsNewArray.map(function(a) {
          return a.age;
        }),
        backgroundColor: ["#acc6ff"],
        label: "New Items",
        pointRadius: 10,
        fill: true
      }]
    },
    options: {
      indexAxis: 'y',
      maintainAspectRatio: false,
      responsive: true,
      layout: {
        padding: 20
      },
      scales: {

        y: {
          ticks: {
            color: "#a3a3a3"
          },
          type: "category",
          labels: whatsNewArray.map(function(a) {
            return a.type;
          }),
          grid: {
            color: "#a3a3a3",
            borderColor: "#a3a3a3"
          }
        },
        x: {
          title: {
            display: true,
            text: "MINUTES AGO",
            color: "#a3a3a3"
          },
          ticks: {
            color: "#a3a3a3"
          },
          beginAtZero: true,
          grid: {
            color: "#a3a3a3",
            borderColor: "#a3a3a3"
          },
          border: {
            color: "#a3a3a3"
          }
        }
      },
      plugins: {
        legend: {
          display: false,
          title: {
            color: "#a3a3a3"
          },
          labels: {
            color: "#a3a3a3"
          }
        },
        title: {
          display: false,
          //text: 'What is New',
          color: "#a3a3a3"
        }
      }
    }
  });
<link href="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/6.1.0/mdb.dark.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/6.1.0/mdb.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.2.0/chart.umd.js"></script>
<div  style="position: relative;width:100%;height:250px;background-color:#283044;">
  <canvas id="myWHATSNEWChart"></canvas>
</div>

CodePudding user response:

I've created this minimal example, for your problem. You can add your custom options as you wish.
You have to treat the y-axis as an index, so .findIndex(el => el.type == elem.type) is checking if the elem.type exists in an array and returns the index of the found element.

var whatsNewArray = [{
    "type": "EAC",
    "age": -16
  },
  {
    "type": "EAC",
    "age": -58
  },
  {
    "type": "DSCC",
    "age": -36
  },
  {
    "type": "SAFE AE",
    "age": -95
  },
  {
    "type": "SAFE AE",
    "age": -94
  },
   {
    "type": "DSCC",
    "age": -2
  },
   {
    "type": "EL",
    "age": -2
  },
   {
    "type": "PSY",
    "age": -20
  },
  {
    "type": "CNGRO",
    "age": -80
  },
  {
    "type": "CNGRO",
    "age": -69
  },
];


let label =  [...new Map(whatsNewArray.map(item =>
                  [item["type"], item["type"]])).values()];

let data = whatsNewArray.map(function(elem, index) {
  return {
    x: elem.age,
    y: label.indexOf(elem.type)
  }
});

const _data = {
  datasets: [{
    label: 'Scatter Dataset',
    data: data,
    backgroundColor: 'rgb(255, 99, 132)'
  }],
};
const config = {
  type: 'scatter',
  data: _data,
  options: {
    responsive: true,
    layout: {
        padding: 20
    },
    pointRadius: 10,
    fill: true,
    scales: {

      y: {
      autofill: false,
        labels: label,
        
        ticks: {
          callback: function(value, index, ticks) {
              
              return value % 1 == 0 ? label[value] : ''
                        
          }
        },
       
      }
    }

  }
};

new Chart(document.getElementById("myWHATSNEWChart"), config);
<link href="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/6.1.0/mdb.dark.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/6.1.0/mdb.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.2.0/chart.umd.js"></script>

<canvas id="myWHATSNEWChart"></canvas>

Explanation: So the index of an array label is being recognized as y-axis data [0,1,2....].

This returns distinct values:

[...new Map(whatsNewArray.map(item => [item["type"], item["type"]])).values()]; 

This checks if the value is an integer, for removing decimal values in this context.

 value % 1 == 0
  • Related