admin管理员组

文章数量:1136270

Please refer this Fiddle : /

I am working on chart.js If you see in fiddle, you will notice that value which is top on bar is not properly displayed in some cases(goes outside the canvas) While research I came across this link how to display data values on Chart.js

But here they used tooltip also for same cases to the text tweak inside of bars. I don't want this.

var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ["2 Jan", "9 Jan", "16 Jan", "23 Jan", "30 Jan", "6 Feb", "13 Feb"],
        datasets: [{
            data: [6, 87, 56, 15, 88, 60, 12],
            backgroundColor: "#4082c4"
        }]
    },
    options: {
        "hover": {
            "animationDuration": 0
        },
        "animation": {
            "duration": 1,
            "onComplete": function () {
                var chartInstance = this.chart,
                ctx = chartInstance.ctx;

                ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
                ctx.textAlign = 'center';
                ctx.textBaseline = 'bottom';

                this.data.datasets.forEach(function (dataset, i) {
                    var meta = chartInstance.controller.getDatasetMeta(i);
                    meta.data.forEach(function (bar, index) {
                        var data = dataset.data[index];                            
                        ctx.fillText(data, bar._model.x, bar._model.y - 5);
                    });
                });
            }
        },
        legend: {
            "display": false
        },
        tooltips: {
            "enabled": false
        },
        scales: {
            yAxes: [{
                display: false,
                gridLines: {
                    display : false
                },
                ticks: {
                    display: false,
                    beginAtZero:true
                }
            }],
            xAxes: [{
                gridLines: {
                    display : false
                },
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});

What I want is to show value on top only, for all cases.

Please refer this Fiddle : https://jsfiddle.net/4mxhogmd/1/

I am working on chart.js If you see in fiddle, you will notice that value which is top on bar is not properly displayed in some cases(goes outside the canvas) While research I came across this link how to display data values on Chart.js

But here they used tooltip also for same cases to the text tweak inside of bars. I don't want this.

var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ["2 Jan", "9 Jan", "16 Jan", "23 Jan", "30 Jan", "6 Feb", "13 Feb"],
        datasets: [{
            data: [6, 87, 56, 15, 88, 60, 12],
            backgroundColor: "#4082c4"
        }]
    },
    options: {
        "hover": {
            "animationDuration": 0
        },
        "animation": {
            "duration": 1,
            "onComplete": function () {
                var chartInstance = this.chart,
                ctx = chartInstance.ctx;

                ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
                ctx.textAlign = 'center';
                ctx.textBaseline = 'bottom';

                this.data.datasets.forEach(function (dataset, i) {
                    var meta = chartInstance.controller.getDatasetMeta(i);
                    meta.data.forEach(function (bar, index) {
                        var data = dataset.data[index];                            
                        ctx.fillText(data, bar._model.x, bar._model.y - 5);
                    });
                });
            }
        },
        legend: {
            "display": false
        },
        tooltips: {
            "enabled": false
        },
        scales: {
            yAxes: [{
                display: false,
                gridLines: {
                    display : false
                },
                ticks: {
                    display: false,
                    beginAtZero:true
                }
            }],
            xAxes: [{
                gridLines: {
                    display : false
                },
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});

What I want is to show value on top only, for all cases.

Share Improve this question edited May 23, 2017 at 12:02 CommunityBot 11 silver badge asked Mar 2, 2017 at 13:30 Kiran ShindeKiran Shinde 5,9626 gold badges29 silver badges45 bronze badges 1
  • If you add a second data object and then you filter the data by the first data object, the values from the second data object will still be visible. Is there a solution to fix this issue? – abautista Commented Jun 19, 2017 at 21:11
Add a comment  | 

9 Answers 9

Reset to default 66

I pulled out the data from being defined inside of myChart that way I could pull out the max value from the dataset. Then inside of the yAxes you can set the max ticks to be the max value + 10 from your data set. This ensures that the top bars in the graph will not go off the edge of the canvas and not display their value.

var ctx = document.getElementById("myChart");
debugger;
var data = {
  labels: ["2 Jan", "9 Jan", "16 Jan", "23 Jan", "30 Jan", "6 Feb", "13 Feb"],
  datasets: [{
    data: [150, 87, 56, 50, 88, 60, 45],
    backgroundColor: "#4082c4"
  }]
}
var myChart = new Chart(ctx, {
  type: 'bar',
  data: data,
  options: {
    "hover": {
      "animationDuration": 0
    },
    "animation": {
      "duration": 1,
      "onComplete": function() {
        var chartInstance = this.chart,
          ctx = chartInstance.ctx;

        ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        this.data.datasets.forEach(function(dataset, i) {
          var meta = chartInstance.controller.getDatasetMeta(i);
          meta.data.forEach(function(bar, index) {
            var data = dataset.data[index];
            ctx.fillText(data, bar._model.x, bar._model.y - 5);
          });
        });
      }
    },
    legend: {
      "display": false
    },
    tooltips: {
      "enabled": false
    },
    scales: {
      yAxes: [{
        display: false,
        gridLines: {
          display: false
        },
        ticks: {
          max: Math.max(...data.datasets[0].data) + 10,
          display: false,
          beginAtZero: true
        }
      }],
      xAxes: [{
        gridLines: {
          display: false
        },
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.js"></script>
<canvas id="myChart" width="100" height="100"></canvas>

The fastest way I found to do this was to use this plugin: https://github.com/chartjs/chartjs-plugin-datalabels

Labels can be added to your charts simply by importing the plugin to the js file e.g.:

import 'chartjs-plugin-datalabels'

And if you want to apply it values on top (globally), simply set these options in your code:

Chart.defaults.global.plugins.datalabels.anchor = 'end';
Chart.defaults.global.plugins.datalabels.align = 'end';

More options can be found here: https://chartjs-plugin-datalabels.netlify.com/options.html

Here is a more robust solution that will display the datapoint value inside the bar for cases where the axis height is close to the bar height. In other words, this will display the value above the bar and/or below the bar if the text will extend beyond the canvas visible area.

Chart.plugins.register({
  afterDraw: function(chartInstance) {
    if (chartInstance.config.options.showDatapoints) {
      var helpers = Chart.helpers;
      var ctx = chartInstance.chart.ctx;
      var fontColor = helpers.getValueOrDefault(chartInstance.config.options.showDatapoints.fontColor, chartInstance.config.options.defaultFontColor);

      // render the value of the chart above the bar
      ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
      ctx.textAlign = 'center';
      ctx.textBaseline = 'bottom';
      ctx.fillStyle = fontColor;

      chartInstance.data.datasets.forEach(function (dataset) {
        for (var i = 0; i < dataset.data.length; i++) {
          var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
          var scaleMax = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._yScale.maxHeight;
          var yPos = (scaleMax - model.y) / scaleMax >= 0.93 ? model.y + 20 : model.y - 5;
          ctx.fillText(dataset.data[i], model.x, yPos);
        }
      });
    }
  }
});

You can enable your chart to use the plugin by adding the below property in your chart options.

showDatapoints: true,

This worked in my case.(plugins section below)

options: {
    responsive: true,
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true,
        }
      }]
    },
    plugins: {
      datalabels: {
        anchor: 'end',
        align: 'top',
        formatter: Math.round,
        font: {
          weight: 'bold'
        }
      }
    }
  }

Happy Coding.

Try these options:

animation: {
  duration: 1,
  onComplete: function({ chart }) {
    const ctx = chart.ctx;

    chart.config.data.datasets.forEach(function(dataset, i) {
      const meta = chart.getDatasetMeta(i);

      meta.data.forEach(function(bar, index) {
        const data = dataset.data[index];

        ctx.fillText(data, bar.x, bar.y - 5);
      });
    });
  }
}

You can use add some padding-top inside your chart options

layout: {
    padding: {
        left: 0,
        right: 0,
        top: 30,
        bottom: 0
    }
 },

You can consider plugin which show data value on top of each bar.

plugins: {
afterDatasetsDraw: function (context, easing) {
 var ctx = context.chart.ctx;
   context.data.datasets.forEach(function (dataset) {
     for (var i = 0; i < dataset.data.length; i++) {
        if (dataset.data[i] != 0) {
          var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
            var textY = model.y + (dataset.type == "line" ? -3 : 15); 
              ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
              ctx.textAlign = 'start';
              ctx.textBaseline = 'middle';
              ctx.fillStyle = dataset.type == "line" ? "black" : "black";
              ctx.save();
              ctx.translate(model.x, textY-15);
              ctx.rotate(4.7);
              ctx.fillText(dataset.data[i], 0, 0);
              ctx.restore();
             }
           }
         });
       }
    }

live code: Link

this works in my case but its show values in mid of the bar.

chart.chart.config.options.animation["onComplete"] =  function () {
        var ctx = chart.chart.ctx;
        ctx.font = '22px "Helvetica Neue", Helvetica, Arial, sans-serif';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        this.data.datasets.forEach(function (dataset) {
            for (var i = 0; i < dataset.data.length; i++) {
                var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
                    scale_max = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._yScale.maxHeight;
                ctx.fillStyle = '#444';
                var y_pos = model.y + 50;
                if ((scale_max - model.y) / scale_max >= 0.5)
                    y_pos = model.y + 20;
                ctx.fillText(dataset.data[i], model.x, y_pos);    
            }
        });                
    }
var ctx = document.getElementById("myChart");
debugger;
var data = {
  labels: ["2 Jan", "9 Jan", "16 Jan", "23 Jan", "30 Jan", "6 Feb", "13 Feb"],
  datasets: [{
    data: [150, 87, 56, 50, 88, 60, 45],
    backgroundColor: "#4082c4"
  }]
}
var myChart = new Chart(ctx, {
  type: 'bar',
  data: data,
  options: {
    "hover": {
      "animationDuration": 0
    },
    "animation": {
      "duration": 1,
      "onComplete": function() {
        var chartInstance = this.chart,
          ctx = chartInstance.ctx;

        ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        this.data.datasets.forEach(function(dataset, i) {
          var meta = chartInstance.controller.getDatasetMeta(i);
          meta.data.forEach(function(bar, index) {
            var data = dataset.data[index];
            ctx.fillText(data, bar._model.x, bar._model.y - 5);
          });
        });
      }
    },
    legend: {
      "display": false
    },
    tooltips: {
      "enabled": false
    },
    scales: {
      yAxes: [{
        display: false,
        gridLines: {
          display: false
        },
        ticks: {
          max: Math.max(...data.datasets[0].data) + 10,
          display: false,
          beginAtZero: true
        }
      }],
      xAxes: [{
        gridLines: {
          display: false
        },
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});

本文标签: javascriptShow values on top of bars in chartjsStack Overflow