How to create a custom legend in ChartJS

I need to create a custom legend for my donut chart using the ChartJS library. I created a donut with a default legend provided by ChartJS, but I need to make some changes.

I would like to matter above the name of the car. Also I don't like the sticky legend, I want it to be separated from the donut so I can change the style of the fonts, boxes (for example, next to the text "Audi")

I know there is a Legend generator , but I'm not sure how to use it with VueJS - because I am using VueJS as a framework

This is what my legend looks like now - http://imgur.com/a/NPUoi

My code:

From the Vue component where I am importing the donut component:

<div class="col-md-6">
  <div class="chart-box">
    <p class="chart-title">Cars</p>
    <donut-message id="chart-parent"></donut-message>
  </div>
</div>

      

Javascript:

    import { Doughnut } from 'vue-chartjs'
    export default Doughnut.extend({

    ready () {


    Chart.defaults.global.tooltips.enabled = false;
    Chart.defaults.global.legend.display = false;

    this.render({
      labels: ['Audi','BMW','Ford','Opel'],
      datasets: [
        {
          label: 'Cars',
          backgroundColor: ['#35d89b','#4676ea','#fba545','#e6ebfd'],
          data: [40, 30, 20, 10]
        }
      ]
    }, 
    {
      responsive: true,
      cutoutPercentage: 75,
      legend: {
        display: true,
        position: "right",
        fullWidth: true,
        labels: {
          boxWidth: 10,
          fontSize: 14
        }
      },
      animation: {
        animateScale: true
      }
    })
  }
});

      

+3


source to share


3 answers


I have the same problem trying to understand the documentation, and this link may clarify the process of setting up legends:

https://codepen.io/michiel-nuovo/pen/RRaRRv

The trick is to track the callback to create your own HTML structure and return that new structure to ChartJS.

Inside options object:

legendCallback: function(chart) {
  var text = [];
  text.push('<ul class="' + chart.id + '-legend">');
  for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
    text.push('<li><span style="background-color:' + 
    chart.data.datasets[0].backgroundColor[i] + '">');
      if (chart.data.labels[i]) {
      text.push(chart.data.labels[i]);
    }
    text.push('</span></li>');
  }
  text.push('</ul>');
  return text.join("");
}

      

Second, you need a container to insert the new html and using the myChart.generateLegend () method to get the customized html:



$("#your-legend-container").html(myChart.generateLegend());

      

After that, if you need, track the events:

$("#your-legend-container").on('click', "li", function() {
  myChart.data.datasets[0].data[$(this).index()] += 50;
  myChart.update();
  console.log('legend: ' + data.datasets[0].data[$(this).index()]);
});

$('#myChart').on('click', function(evt) {
  var activePoints = myChart.getElementsAtEvent(evt);
  var firstPoint = activePoints[0];
  if (firstPoint !== undefined) {
    console.log('canvas: ' + 
    data.datasets[firstPoint._datasetIndex].data[firstPoint._index]);
  } 
  else {
    myChart.data.labels.push("New");
    myChart.data.datasets[0].data.push(100);
    myChart.data.datasets[0].backgroundColor.push("red");
    myChart.options.animation.animateRotate = false;
    myChart.options.animation.animateScale = false;
    myChart.update();
    $("#your-legend-container").html(myChart.generateLegend());
  }
}

      

Another solution I found, if you don't need to change the HTMl structure inside the legend, you can just paste the same HTML into your legend container and customize it with CSS, check this other link:

http://jsfiddle.net/vrwjfg9z/

Hope it works for you.

+3


source


You can extract the markup for the legend.

data () {
  return {
     legendMarkup: ''
  }
},
ready () {
  this.legendMarkup = this._chart.generateLegend()
 }

      

And in your template, you can output it.



<div class="legend" ref="legend" v-html="legendMarkup"></div>

      

this._chart is the internal chartjs instance in vue-chartjs. This way you can call all chartjs methods that are not displayed by the vue-chartjs api above it.

However, you can also use the legend generator. The usage in VUE is the same. You can pass parameters, use callbacks, etc.

0


source


please check the documentation .

Legends configuration

The chart legend displays the data about the datasets that are displayed in the chart.

Configuration options Legend position. Possible options:

'top' 'left' 'bottom' 'Right'

Legend description interface

Items passed to the onClick legend function are returned from label.generateLabels. These elements must implement the following interface.

{
    // Label that will be displayed
    text: String,

    // Fill style of the legend box
    fillStyle: Color,

    // If true, this item represents a hidden dataset. Label will be rendered with a strike-through effect
    hidden: Boolean,

    // For box border. See https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap
    lineCap: String,

    // For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
    lineDash: Array[Number],

    // For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
    lineDashOffset: Number,

    // For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin
    lineJoin: String,

    // Width of box border
    lineWidth: Number,

    // Stroke style of the legend box
    strokeStyle: Color

    // Point style of the legend box (only used if usePointStyle is true)
    pointStyle: String
}

      

Example

The following example will create a chart with legend enabled and rotate all text to red.

var chart = new Chart (ctx, {type: "bar", data: data, options: {Legend: {display: true, labels: {fontColor: 'rgb (255, 99, 132)'}}}}); Custom click actions

You can usually click an item in the legend to trigger a different behavior. This can be easily achieved using a callback in the config object.

Default click handler:

function(e, legendItem) {
    var index = legendItem.datasetIndex;
    var ci = this.chart;
    var meta = ci.getDatasetMeta(index);

    // See controller.isDatasetVisible comment
    meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;

    // We hid a dataset ... rerender the chart
    ci.update();
}
Lets say we wanted instead to link the display of the first two datasets. We could change the click handler accordingly.

var defaultLegendClickHandler = Chart.defaults.global.legend.onClick;
var newLegendClickHandler = function (e, legendItem) {
    var index = legendItem.datasetIndex;

    if (index > 1) {
        // Do the original logic
        defaultLegendClickHandler(e, legendItem);
    } else {
        let ci = this.chart;
        [ci.getDatasetMeta(0),
         ci.getDatasetMeta(1)].forEach(function(meta) {
            meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
        });
        ci.update();
    }
};

var chart = new Chart(ctx, {
    type: 'line',
    data: data,
    options: {
        legend: {

        }
    }
});

      

Now when you click on the legend on this chart, the visibility of the first two datasets will be linked.

HTML legends

Sometimes you need a very complex legend. In these cases, it makes sense to generate an HTML legend. Graphs provide a generateLegend () method for their prototype, which returns the HTML string for the legend.

To customize how this legend is generated, you can change the legendCallback config property.

var chart = new Chart(ctx, {
    type: 'line',
    data: data,
    options: {
        legendCallback: function(chart) {
            // Return the HTML string here.
        }
    }
});

      

-2


source







All Articles