【问题标题】:How can I append a calculated value to the end of a bar in Chart.JS?如何在 Chart.JS 中将计算值附加到条形的末尾?
【发布时间】:2016-09-21 22:46:52
【问题描述】:

我正在生成一个如下所示的水平条形图:

我需要它看起来像这样:

也就是说,我需要将第 1 周(顶部/绿色条)和第 2 周(底部/橙色条)之间的百分比差异附加到第 2 周条。

我正在使用此代码将 vals 添加到条本身:

Chart.pluginService.register({
    afterDraw: function (chartInstance) {
        var ctx = chartInstance.chart.ctx;
        // render the value of the chart above the bar
        ctx.font = Chart.helpers.fontString(14, 'bold', Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        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;
                ctx.fillText(addCommas(dataset.data[i]), model.base + 20, model.y + 6);
            }
        });
    }
});

...但不知道如何进行计算并将其附加到条形的末尾。

对于完整的“monty”,这里是该图表的 jQuery 的其余部分:

var ctxForecastChart = $("#forecastLineChart").get(0).getContext("2d");
var forecastChartData = {
    labels: [
        "Total Qty", "Total Sales"
    ],
    datasets: [
        {
            label: "9/18/2016",
            backgroundColor: "rgba(34,139,34,0.75)",
            hoverBackgroundColor: "rgba(34,139,34,1)",
            data: [100, 1000.00]
        },
        {
            label: "9/25/2016",
            backgroundColor: "rgba(255,153,51,0.75)",
            hoverBackgroundColor: "rgba(255,153,51,1)",
            data: [110, 1110.11]
        }
    ]
};

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

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

更新

Tektiv 的代码看起来很有前途,但由于某种原因它完全打破了我的图表。使用我的代码:

Chart.pluginService.register({
    afterDraw: function (chartInstance) {
        var ctx = chartInstance.chart.ctx;
        // render the value of the chart above the bar
        ctx.font = Chart.helpers.fontString(14, 'bold', Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        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;
                ctx.fillText(addCommas(dataset.data[i]), model.base + 20, model.y + 6);
            }
        });
    }
});

...我看到了:

用新代码替换上面的代码:

Chart.pluginService.register({
    afterDraw: function (chartInstance) {
        var ctx = chartInstance.chart.ctx;
        ctx.font = Chart.helpers.fontString(14, 'bold', Chart.defaults.global.defaultFontFamily);

        // `start` makes a better rendering IMO
        ctx.textAlign = 'start';
        ctx.textBaseline = 'bottom';
        ctx.fillStyle = '#666';

        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;
                ctx.fillText(dataset.data[i], model.base + 5, model.y + 6);

                if (i == 1) {
                    // `Total Sales` values here

                    // If needed, here you get the other dataset
                    var otherDataset = chartInstance.data.datasets[(dataset._meta[0].controller.index == 1) ? 0 : 1];

                    // Get the value you want to display
                    var value = Math.round((Math.abs(dataset.data[i] - otherDataset.data[i]) / dataset.data[i]) * 100);

                    // Display it with the `x` property of the model
                    ctx.fillText(value + "%", model.x + 5, model.y + 6);
                }
            }
        });
    }
});

...我看到了:

我不知道为什么 - 新代码看起来不错,AFAICT。

更新 2

更新后的代码稍微好一点,但它仍然扭曲了其他图表:

更新 3

显然这是决斗 OnDraw() 事件的问题;我也有这个针对价格合规图表:

Chart.pluginService.register({
    afterDraw: function (chartInstance) {
        var ctx = chartInstance.chart.ctx;
        // render the value of the chart above the bar
        ctx.font = Chart.helpers.fontString(14, 'bold', Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        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;
                ctx.fillText(addCommas(dataset.data[i]), model.base + 20, model.y + 6);
                //ctx.fillText(dataset.data[i], model.base + 20, model.y + 6);
            }
        });
    }
});

【问题讨论】:

  • 您如何获得这些10%11.1% 值?我没有得到这部分
  • 带油漆;这就是我希望图表看起来如何的示例;这是我的问题:我怎样才能让它看起来像那样?
  • 这里的小误会。我的意思是你如何计算这些值?我没有得到你所说的差异的部分。你在做 (orange / green, green / orange ...) 吗?
  • 第一组值是一种颜色,另一组是另一种颜色,如 forecastChartData 的数据集部分中所指定。我还没有一种以编程方式计算价值的方法——这是另一个问题。现在我正在使用计算器(差除以原始数字 * 100)。

标签: javascript jquery chart.js chart.js2


【解决方案1】:

正如您在添加数据时对 model.base 所做的那样,请执行以下操作:

Chart.pluginService.register({
    afterDraw: function(chartInstance) {
        var ctx = chartInstance.chart.ctx;
        ctx.font = Chart.helpers.fontString(14, 'bold', Chart.defaults.global.defaultFontFamily);

        // `start` makes a better rendering IMO
        ctx.textAlign = 'start';
        ctx.textBaseline = 'bottom';
        ctx.fillStyle = '#666';

        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;
                ctx.fillText(dataset.data[i], model.base + 5, model.y + 6);

                if (dataset._meta[0].controller.index == 1) {
                    // Orange bar (2nd dataset) values here

                    // We get the other dataset
                    var otherDataset = chartInstance.data.datasets[(dataset._meta[0].controller.index == 1) ? 0 : 1];

                    // Then calculate the percentage difference
                    var value = Math.round((Math.abs(dataset.data[i] - otherDataset.data[i]) / otherDataset.data[i]) * 100);

                    // And finally we display it
                    ctx.fillText(value + "%", model.x + 5, model.y + 6);
                }
            }
        });
    }
});


您可以看到该插件正在运行in this jsFiddle,它的外观如下:

【讨论】:

  • 我刚刚意识到我的要求是错误的; “10%”实际上应该附加到“110”条(第 2 周是 10% 的数量改进),而 11% 应该附加到第 2 周的销售额。我将替换“这就是我想要的样子”图像。
  • @B.ClayShannon 我编辑了所有内容(代码、小提琴 ..)以满足您的新要求。没事吧?
  • 看起来棒极了;我会捷克的。请查看我对我遇到的问题的更新(我会看看新代码是否会改变)。好一点,但仍然打破其他图表;请参阅更新 2。
  • @B.ClayShannon 问题在于插件会影响页面上的所有图表。如果您可以制作一段包含 4 个图表的代码(例如使用 jsFiddle),那就太好了,因为我可以看看有什么不工作的地方。
  • 没有办法将代码限制为单个图表?我需要另一个图表的单独功能。我会在更新 3 中展示它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-10
  • 2015-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多