Chart.js动态条宽度 [英] Chart.js dynamic bar width

查看:231
本文介绍了Chart.js动态条宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要呈现一组连续块的时间序列数据。



我需要描述一系列可能跨越多个小时甚至只是分钟,并带有自己的Y值。



我不确定ChartJS是否应用于此目的,但我已经研究了扩展Bar类型,但是似乎很难将每个条形编码为相同的宽度。



我正在尝试实现在Excel中可用的类似功能:

解决方案

我发现我需要这样做,@ potatopeelings的回答很棒,但对于Chartjs版本2来说已经过时了。我通过扩展栏创建了自己的控制器/图表类型,做了类似的事情:

  // controller.barw.js 

module.exports = function(Chart){

var helpers = Chart.helpers;

Chart.defaults.barw = {
悬停:{
模式:'label'
},

比例尺:{
x轴:[{
类型:类别,

//特定于酒吧控制器
类别百分比:0.8,
bar百分比:0.9,

//网格线设置
gridLines:{
offsetGridLines:true
}
}],
y轴:[{
type:'线性'
}]
}
};

Chart.controllers.barw = Chart.controllers.bar.extend({

/ **
* @private
* /
getRuler:function(){
var me = this;
var scale = me.getIndexScale();
var options = scale.options;
var stackCount = me.getStackCount ();
var fullSize = scale.isHorizo​​ntal()?scale.width:scale.height;
var tickSize = fullSize / scale.ticks.length;
var categorySize = tickSize *选项。 categoryPercentage;
var fullBarSize = categorySize / stackCount;
var barSize = fullBarSize * options.barPercentage;

barSize = Math.min(
helpers.getValueOrDefault(options。 barThickness,barSize),
helpers.getValueOrDefault(options.maxBarThickness,Infinity));

return {
fullSize:fullSize,
stackCount:stackCount,
tickSize:tickSize,
categorySize:categorySize,
categorySpacing:tickSize-categorySize,
fullBarSize:fullBarSize,
barSize:barSize,
barSpacing:fullBarSize-barSize,
scale:scale
};
},


/ **
* @private
* /
computeBarIndexPixels:function(datasetIndex,index,Ruler){ b $ b var me = this;
var scale = ruler.scale;
var选项= scale.options;
var isCombo = me.chart.isCombo;
var stackIndex = me.getStackIndex(datasetIndex);
var base = scale.getPixelForValue(null,index,datasetIndex,isCombo);
var size = ruler.barSize;

var数据集= me.chart.data.datasets [datasetIndex];
if(dataset.weights){
var total = dataset.weights.reduce((m,x)=> m + x,0);
var perc = dataset.weights [index] / total;
var offset = 0;
for(var i = 0; i< index; i ++){
offset + = dataset.weights [i] / total;
}
var pixelOffset = Math.round(ruler.fullSize * offset);
var base = scale.isHorizo​​ntal()吗? scale.left:scale.top;
base + = pixelOffset;

size = Math.round(ruler.fullSize * perc);
size-= ruler.categorySpacing;
size-= ruler.barSpacing;
}

base-= isCombo? ruler.tickSize / 2:0;
base + = ruler.fullBarSize * stackIndex;
base + = ruler.categorySpacing / 2;
base + = ruler.barSpacing / 2;

return {
size:size,
base:base,
head:base + size,
center:base + size / 2
};
},
});
};

然后,您需要像这样将其添加到您的chartjs实例中:

 从'chart.js'导入图表
从'controller.barw'导入barw

barw(图表); //将插件添加到chartjs

最后,类似于其他答案,条宽度的权重需要添加到数据集中:

  var data = {
标签:['A','B ','C','D','E','F','G'],
数据集:[
{
标签:我的第一个数据集,
fillColor: rgba(220,220,220,0.5),
strokeColor: rgba(220,220,220,0.8),
HighlightFill: rgba(220,220,220,0.7),
HighlightStroke: rgba (220,220,220,1),
数据:[65、59、80、30、56、65、40],
权重:[1、0.9、1、2、1、4、0.3]
},
]
};

这有望使某人走上正确的道路。我当然不完美,但是如果您确保对数据点有正确的权重数量,那么您应该是对的。



祝您好运。 / p>

I have a requirement to render a set of time series data of contiguous blocks.

I need to describe a series of bars which could span many hours, or just minutes, with their own Y value.

I'm not sure if ChartJS is what I should be using for this, but I have looked at extending the Bar type, but it seems very hard coded for each bar to be the same width. The Scale Class internally is used for labels, chart width etc, not just the bars themselves.

I am trying to achieve something like this that works in Excel: http://peltiertech.com/variable-width-column-charts/

Has anyone else had to come up with something similar?

解决方案

I found I needed to do this and the answer by @potatopeelings was great, but out of date for version 2 of Chartjs. I did something similar by creating my own controller/chart type via extending bar:

//controller.barw.js

module.exports = function(Chart) {

    var helpers = Chart.helpers;

    Chart.defaults.barw = {
        hover: {
            mode: 'label'
        },

        scales: {
            xAxes: [{
                type: 'category',

                // Specific to Bar Controller
                categoryPercentage: 0.8,
                barPercentage: 0.9,

                // grid line settings
                gridLines: {
                    offsetGridLines: true
                }
            }],
            yAxes: [{
                type: 'linear'
            }]
        }
    };

    Chart.controllers.barw = Chart.controllers.bar.extend({

        /**
         * @private
         */
        getRuler: function() {
            var me = this;
            var scale = me.getIndexScale();
            var options = scale.options;
            var stackCount = me.getStackCount();
            var fullSize = scale.isHorizontal()? scale.width : scale.height;
            var tickSize = fullSize / scale.ticks.length;
            var categorySize = tickSize * options.categoryPercentage;
            var fullBarSize = categorySize / stackCount;
            var barSize = fullBarSize * options.barPercentage;

            barSize = Math.min(
                helpers.getValueOrDefault(options.barThickness, barSize),
                helpers.getValueOrDefault(options.maxBarThickness, Infinity));

            return {
                fullSize: fullSize,
                stackCount: stackCount,
                tickSize: tickSize,
                categorySize: categorySize,
                categorySpacing: tickSize - categorySize,
                fullBarSize: fullBarSize,
                barSize: barSize,
                barSpacing: fullBarSize - barSize,
                scale: scale
            };
        },


        /**
         * @private
         */
        calculateBarIndexPixels: function(datasetIndex, index, ruler) {
            var me = this;
            var scale = ruler.scale;
            var options = scale.options;
            var isCombo = me.chart.isCombo;
            var stackIndex = me.getStackIndex(datasetIndex);
            var base = scale.getPixelForValue(null, index, datasetIndex, isCombo);
            var size = ruler.barSize;

            var dataset = me.chart.data.datasets[datasetIndex];
            if(dataset.weights) {
                var total = dataset.weights.reduce((m, x) => m + x, 0);
                var perc = dataset.weights[index] / total;
                var offset = 0;
                for(var i = 0; i < index; i++) {
                    offset += dataset.weights[i] / total;
                }
                var pixelOffset = Math.round(ruler.fullSize * offset);
                var base = scale.isHorizontal() ? scale.left : scale.top;
                base += pixelOffset;

                size = Math.round(ruler.fullSize * perc);
                size -= ruler.categorySpacing;
                size -= ruler.barSpacing;
            }            

            base -= isCombo? ruler.tickSize / 2 : 0;
            base += ruler.fullBarSize * stackIndex;
            base += ruler.categorySpacing / 2;
            base += ruler.barSpacing / 2;

            return {
                size: size,
                base: base,
                head: base + size,
                center: base + size / 2
            };
        },
    });
};

Then you need to add it to your chartjs instance like this:

import Chart from 'chart.js'
import barw from 'controller.barw'

barw(Chart); //add plugin to chartjs

and finally, similar to the other answer, the weights of the bar widths need to be added to the data set:

var data = {
    labels: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
    datasets: [
        {
            label: "My First dataset",
            fillColor: "rgba(220,220,220,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.7)",
            highlightStroke: "rgba(220,220,220,1)",
            data: [65, 59, 80, 30, 56, 65, 40],
            weights: [1, 0.9, 1, 2, 1, 4, 0.3]
        },
    ]
};

This will hopefully get someone onto the right track. What I have certainly isn't perfect, but if you make sure you have the right number of weight to data points, you should be right.

Best of luck.

这篇关于Chart.js动态条宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆