【问题标题】:How can I add a label above just the last bar in a Chart.JS bar chart?如何在 Chart.JS 条形图中的最后一个条上方添加标签?
【发布时间】:2016-09-27 22:00:17
【问题描述】:

我正在创建这样的条形图:

var ctxForecastChart = $("#forecastLineChart").get(0).getContext("2d");
var forecastChartData = {
    labels: [
        "Total Sales"
    ],
    datasets: [
    {
        label: "8/28/2016 - 9/3/2016",
        backgroundColor: "rgba(255,0,0,0.75)",
        hoverBackgroundColor: "rgba(255,0,0,1)",
        data: [240]
    },
    {
        label: "9/25/2016 - 10/2/2016",
        backgroundColor: "rgba(255,153,0,0.75)",
        hoverBackgroundColor: "rgba(255,153,0,1)",
        data: [272]
    },
    {
        label: "9/18/2016 - 9/24/2016",
        backgroundColor: "rgba(255,255,0,0.75)",
        hoverBackgroundColor: "rgba(255,255,0,1)",
        data: [250]
    },
    {
        label: "9/4/2016 - 9/10/2016",
        backgroundColor: "rgba(0,255,0,0.75)",
        hoverBackgroundColor: "rgba(0,255,0,1)",
        data: [232]
    },
    {
        label: "9/11/2016 - 9/17/2016",
        backgroundColor: "rgba(0,0,255,0.75)",
        hoverBackgroundColor: "rgba(0,0,255,1)",
        data: [244]
    }]
};

var forecastOptions = {
    tooltips: {
        enabled: true
    }
};

var forecastBarChart = new Chart(ctxForecastChart,
{
    type: 'bar',
    data: forecastChartData,
    options: forecastOptions
});

看起来像这样:

我想要做的是在最后一个栏(蓝色)上方添加一个标签,其中前一个/第四个和那个之间有百分比差异。在这种情况下,该值应为“+5.2%”,使其看起来像这样:

我认为这将需要注册 afterDraw() 事件,但它应该是什么样子的细节超出了我的范围。

更新

如果我将其添加到建议的代码中:

if (chartInstance.id !== 2) return; // affect this one only

在上下文中:

afterDraw: function (chartInstance) {
    if (chartInstance.id !== 2) return; // affect this one only
    // We get the canvas context
    var ctx = chartInstance.chart.ctx;

...结果比没有它要好一点(它破坏了我的第一个(饼图)图表并完全消除了接下来的两个(包括这里讨论的那个):

如您所见,饼图仍然被冲洗,两个条形图中的值被缩小,就好像一个食人部落对它们实施了邪恶的把戏。而且,最后一个栏没有任何附加值。

【问题讨论】:

    标签: javascript drawing draw chart.js chart.js2


    【解决方案1】:

    首先,您考虑将afterDraw 事件与plugin 结合使用是正确的,我知道在所有数据和选项中找到我们真正想要的内容可能会很混乱。

    然而,遵循一个插件可以帮助你做你正在寻找的东西:

    var myPlugin = {
        afterDraw: function(chartInstance) {
            // We get the canvas context
            var ctx = chartInstance.chart.ctx;
    
            // And set all the properties we need
            ctx.font = Chart.helpers.fontString(14, 'bold', Chart.defaults.global.defaultFontFamily);
            ctx.textAlign = 'center';
            ctx.textBaseline = 'bottom';
            ctx.fillStyle = '#666';
    
            // We get the number of datasets we have in your chart
            var numOfDatasets = chartInstance.config.data.datasets.length;
    
            // For every dataset in our chart ...
            chartInstance.data.datasets.forEach(function(dataset) {
    
                // If it is not the last dataset, we return now (no action at all)
                if (dataset._meta[0].controller.index != numOfDatasets - 1) return;
    
                // For every data in the dataset ...
                for (var i = 0; i < dataset.data.length; i++) {
    
                    // We get the previous dataset (to compare later)
                    var previousDataset = chartInstance.config.data.datasets[dataset._meta[0].controller.index - 1];
                    // And get the model of the current value
                    var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
    
                    // We calculate the percentage difference with the previous
                    var value = ((dataset.data[i] - previousDataset.data[i]) / previousDataset.data[i]) * 100;
    
                    // And write it with a "%" symbol
                    // The ternary adds a "+" symbol if it is a positive value
                    ctx.fillText((value > 0 ? "+" : "") + value.toFixed(1) + "%", model.x, model.y);
                }
            });
        }
    };
    
    Chart.pluginService.register(myPlugin);
    


    您可以看到此代码在 on this jsFiddle 工作,这是它的结果:

    【讨论】:

    • 不幸的是,这破坏了我的第一个图表(饼图)并完全抹杀了接下来的两个(包括这里讨论的那个)。
    • @B.ClayShannon 即使使用 if (chartInstance.id != 1) return; ?我成功地让它工作了on this updated fiddle
    • 我可以把afterDraw事件放在图表构造函数中吗?在 "var forecastBarChart = new Chart(ctxForecastChart, { type: 'bar'," 之后会有什么不同吗?
    • @B.ClayShannon 据我所知,插件只能放在调用之前,甚至不能放在里面,因为你编辑了全局信息(你可以看到Chart.前缀)跨度>
    • @B.ClayShannon 如果您在同一页面上有多个图表,则很难处理插件。你使用animation.onComplete 回调做得很好! --- 但是,您应该注意,您所做的不是插件,它是 Chart.js 内置选项的一部分。
    猜你喜欢
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多