1

Good day to all:

Recently I have started working with Vue.js(2.6.12) + Vuetify(2.3.10) and Chart.js(3.0.2). So I'm a newbie (again).

I have created a componenent which wraps the Bar chart that Chart.js allows us to create. Here it's a picture of it:Component created

The only two things that I want to change are the little box that comes near to the legend title and some grid x lines.

In the case of the little legend box is red. I would like that It's aligned with the blue color of the legend title text. As I show you in this picture:Box and legend title textResult that I would like to achieve

Finally I want to include some color (pink) in the X axis:

I'm unable to achieve this. I have regarded and follow the official documentation and nothing works :S.

In the case of the legend title box I have noticed that always takes the color of the first element. In the case of the axis, the function supported by chart.js doesn't work for me. It doesn't print me the x axis at all.

Things that I have tried:

  • Upgrade to chart.js 3.3.0 but I got an error like this: "" The reason I was using 3.0.2 it's because it's the only version which is working to me from the 3.0.0 versions.
  • Downgrade to 2.9.3/4. I wasn't able to change the color of the box or the axis lines, but the rest worked fine.
  • Use a wrapper: https://vue-chartjs.org/. It didn't work

Code of the whole component:

<template>
  <div class="container pa-3" fill-height fluid style="width: 100%">
    <!-- We create the chart -->
    <canvas id="myChart1" />
  </div>
</template>

<script>
import Chart from "chart.js/auto";

export default {
  name: "Chart",

  components: {},

  props: {},

  data: () => ({
    ctx: null,
    myChart: null,
    type: "bar",
    data: {
      labels: ["a", "b", "c", "d"],
      datasets: [
        {
          data: [1, 2, 3, 4],
          backgroundColor: ["#c30", "#e37609", "#ffda05", "#fffb05"],
        },
      ],
    },
    options: {
      plugins: {
        legend: {
          display: true,
          labels: {
            color: "#00a3fb",
          },
        },
      },
      scales: {
   
      },
    },
  }),
  methods: {
    createChart: function () {
      // destroy the previous graph
      if (this.myChart != null) this.myChart.destroy();
      // create a new one
      this.ctx = document.getElementById("myChart1");
      this.myChart = new Chart(this.ctx, {
        type: this.type,
        data: this.data,
        options: this.options,
      });
      this.myChart.render();
    },
  },

  destroyed() {},

  mounted() {
    this.createChart();
  },
  watch: {},
};
</script>

<style scoped>
</style>

For using it, you should:

  • Import it in the section
  • Declare it in the component section
  • Call it by <NameOfComponetGiven/> tag

Any help would be quite aprecciated. Thank you very much.

  • Can you please specify the error why you are not using a more up to date version of the lib instead of empty qoutes – LeeLenalee May 26 '21 at 14:35

1 Answers1

1

To customize the legend box color you will need to use a custom HTML legend, there you can specify it with CSS, for the pink grid lines you can use the scriptable options. For both see example:

const getOrCreateLegendList = (chart, id) => {
  const legendContainer = document.getElementById(id);
  let listContainer = legendContainer.querySelector('ul');

  if (!listContainer) {
    listContainer = document.createElement('ul');
    listContainer.style.display = 'flex';
    listContainer.style.flexDirection = 'row';
    listContainer.style.margin = 0;
    listContainer.style.padding = 0;

    legendContainer.appendChild(listContainer);
  }

  return listContainer;
};

const htmlLegendPlugin = {
  id: 'htmlLegend',
  afterUpdate(chart, args, options) {
    const ul = getOrCreateLegendList(chart, options.containerID);

    // Remove old legend items
    while (ul.firstChild) {
      ul.firstChild.remove();
    }

    // Reuse the built-in legendItems generator
    const items = chart.options.plugins.legend.labels.generateLabels(chart);

    items.forEach(item => {
      const li = document.createElement('li');
      li.style.alignItems = 'center';
      li.style.cursor = 'pointer';
      li.style.display = 'flex';
      li.style.flexDirection = 'row';
      li.style.marginLeft = '10px';

      li.onclick = () => {
        const {
          type
        } = chart.config;
        if (type === 'pie' || type === 'doughnut') {
          // Pie and doughnut charts only have a single dataset and visibility is per item
          chart.toggleDataVisibility(item.index);
        } else {
          chart.setDatasetVisibility(item.datasetIndex, !chart.isDatasetVisible(item.datasetIndex));
        }
        chart.update();
      };

      // Color box
      const boxSpan = document.createElement('span');
      boxSpan.style.background = options.legendBoxColor || item.fillStyle;
      boxSpan.style.borderColor = item.strokeStyle;
      boxSpan.style.borderWidth = item.lineWidth + 'px';
      boxSpan.style.display = 'inline-block';
      boxSpan.style.height = '20px';
      boxSpan.style.marginRight = '10px';
      boxSpan.style.width = '20px';

      // Text
      const textContainer = document.createElement('p');
      textContainer.style.color = options.legendTextColor || item.fontColor;
      textContainer.style.margin = 0;
      textContainer.style.padding = 0;
      textContainer.style.textDecoration = item.hidden ? 'line-through' : '';

      const text = document.createTextNode(item.text);
      textContainer.appendChild(text);

      li.appendChild(boxSpan);
      li.appendChild(textContainer);
      ul.appendChild(li);
    });
  }
};

const options = {
  type: 'bar',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      borderWidth: 1,
      backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"]
    }]
  },
  options: {
    scales: {
      x: {
        grid: {
          color: (line) => ((line.index === 2 || line.index === 3) ? 'pink' : 'rgba(0,0,0,0.1)'),
          lineWidth: (line) => ((line.index === 2 || line.index === 3) ? 6 : 1)
        }
      }
    },
    plugins: {
      htmlLegend: {
        // ID of the container to put the legend in
        containerID: 'legendContainer',
        legendBoxColor: 'blue',
        legendTextColor: 'blue'
      },
      legend: {
        display: false,
      }
    }
  },
  plugins: [htmlLegendPlugin]
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <div id="legendContainer"></div>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.0.2/chart.js"></script>
</body>
LeeLenalee
  • 27,463
  • 6
  • 45
  • 69