Home > Back-end >  Having trouble with Charts.js colors
Having trouble with Charts.js colors

Time:06-29

A friend helped me get Charts.js working and I'm now trying to mentally reverse engineer what he's done that works for displaying the data to make the data display how I'd like. There's typically 8-10 lines to draw, so I'm trying to make the data easier to read by introducing colour.

I was able to get the lines to each have a unique color by setting values for borderColor, however the points that appear on the line don't match the line and instead change as they go along the line. I'd like the points to be consistent with the line. I'm not sure where I've gone wrong there. Can someone please help me fix these color issues?

Line graph of many colors

For simplicity I've trimmed the code below to 3 colours, but I have 11 mapped out in my code. The below will cycle 3 point colors along each line. What I'm after is the line colour, background and point color to match.

<script setup lang="ts">
import { Line } from "vue-chartjs";
import {
  Chart as ChartJS,
  Title,
  Tooltip,
  Legend,
  LineElement,
  LinearScale,
  PointElement,
  CategoryScale,
} from "chart.js";
import type { DataYearlyGrowth} from "@/types/myData";
import { useDark } from "@vueuse/core";

ChartJS.register(
  Title,
  Tooltip,
  Legend,
  LineElement,
  LinearScale,
  PointElement,
  CategoryScale
);

const props = defineProps<{ data: Array<DataYearlyGrowth> }>();

const chartId = "line-chart";
const datasetIdKey = "label";
const width = 300;
const height = 100;
const styles = {};

const yearlyGrowthValues = props.data;
const years = [...new Set(yearlyGrowthValues.map((x) => x.year.toString()))];

const dataByTypes = yearlyGrowthValues.reduce((rv, x) => {
  (rv[x.type] = rv[x.type] || []).push(x.value);
  return rv;
}, {} as { [key: string]: Array<any> });

const chartData = {
  labels: years,
  datasets: Object.keys(dataByTypes).map((key) => ({
    text: 'Yearly growth',
    label: key,     // TODO: Make the font colour white
    data: dataByTypes[key],
    hoverBackgroundColor: 'rgba(211, 211, 211, 0.8)',
    borderColor:    // Line colour
      [
        'rgba(138, 20, 21, 0.8)',
        'rgba(241, 16, 22, 0.8)',
        'rgba(249, 148, 0, 0.8)'
      ],
    backgroundColor: // Middle of line colour. Just colours the square in the key
       [
         'rgba(138, 20, 21, 1)',
         'rgba(241, 16, 22, 1)',
         'rgba(249, 148, 0, 1)'
       ],
    pointBackgroundColor:   // Colours the middle of the points where data intersects years
      [
        'rgba(138, 20, 21, 0.8)',
        'rgba(241, 16, 22, 0.8)',
        'rgba(249, 148, 0, 0.8)'
      ],
    fill: true,
    borderWidth: 2,
    cubicInterpolationMode: 'monotone',
    //stepped:  'middle',
    stepped: false,
    borderJoinStyle: "round",
    tension: 0.2,
  }))
};

const chartOptions = {
responsive: true,
};

</script>

<template>
  <div >
    <Line
      :chart-options="chartOptions"
      :chart-data="chartData as any"
      :chart-id="chartId"
      :dataset-id-key="datasetIdKey"
      :plugins="[]"
      :styles="styles"
      :width="width"
      :height="height"
    />
  </div>
</template>

Also, I'm trying to get Labels to display in white I tried this, but it made no difference

const chartOptions = {
 legend: {
   labels: {
    fontColor: 'white' 
   }
 },
responsive: true,
};

CodePudding user response:

This is because you define your collors as arrays, if you want a static color you need to supply only 1 static color like so:

const colors = [
  'rgba(138, 20, 21, 0.8)',
  'rgba(241, 16, 22, 0.8)',
  'rgba(249, 148, 0, 0.8)'
];

const chartData = {
  labels: years,
  datasets: Object.keys(dataByTypes).map((key, i) => ({
    text: 'Yearly growth',
    label: key,     // TODO: Make the font colour white
    data: dataByTypes[key],
    hoverBackgroundColor: 'rgba(211, 211, 211, 0.8)',
    borderColor: colors[i % colors.length], // Get color for this index, roll over if index is larger then array size
    backgroundColor: colors[i % colors.length], // Get color for this index, roll over if index is larger then array size
    pointBackgroundColor: colors[i % colors.length], // Get color for this index, roll over if index is larger then array size
    fill: true,
    borderWidth: 2,
    cubicInterpolationMode: 'monotone',
    //stepped:  'middle',
    stepped: false,
    borderJoinStyle: "round",
    tension: 0.2,
  }))
};
  • Related