Chart Js 更改 Ox 轴上的文本标签方向 [英] Chart Js change text label orientation on Ox axis

查看:12
本文介绍了Chart Js 更改 Ox 轴上的文本标签方向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 chartJS 库 - http://www.chartjs.org/

I am using chartJS library - http://www.chartjs.org/

如果文字标签过大,chartJs会以45度角显示文字请告诉我如何将文本旋转更改为 30 度.

If the text label is too big, chartJs displays text at 45 degrees Please tell me how can I change the text rotation to 30 degrees for instance.

请看以下内容:

    var data = {   labels:['Large Text Very Large','Text1','Text2'],
                 datasets:[ { label:'DS1',
                              fillColor:'rgba(228,218,86,0.5)',  
                             strokeColor:'rgba(228,218,86,0.8)',
                              highlightFill:'rgba(228,218,86,0.75)',
                              highlightStroke: 'rgba(228,218,86,1)', data:[0,1,0]
                            }
                 ]
           }


    var options = {
        animation: false
    };

    //Get the context of the canvas element we want to select
    var c = $('#myChart');
    var ct = c.get(0).getContext('2d');
    var ctx = document.getElementById("myChart").getContext("2d");
    /*************************************************************************/
    myNewChart = new Chart(ct).Bar(data, options);

同样在 jsfiddle 上:

Also on jsfiddle:

http://jsfiddle.net/cvL9fk2t/

谢谢!

推荐答案

您需要扩展 scale 类并覆盖 calculateXLabelRotation 方法以使用用户输入的旋转而不是尝试解决它是自己.如果这样做,则需要扩展条形图或折线图并覆盖 init 方法以使用此比例类.(或者您可以直接对比例、条形和线条类进行这些更改,然后无需覆盖).

You would need to extend the scale class and override the calculateXLabelRotation method to use a user inputted rotation rather than trying to work it out it's self. If you do this you would then need to extend the bar or line chart and override the init method to make use of this scale class. (or you could make these changes directly to the scale, bar and line classes and then no need to override).

所以首先扩展 scale 类并使其使用用户定义的选项

so first extend scale class and make it use a user defined option

var helpers = Chart.helpers;
Chart.MyScale = Chart.Scale.extend({
    calculateXLabelRotation: function() {
        //Get the width of each grid by calculating the difference
        //between x offsets between 0 and 1.

        this.ctx.font = this.font;

        var firstWidth = this.ctx.measureText(this.xLabels[0]).width,
            lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,
            firstRotated,
            lastRotated;


        this.xScalePaddingRight = lastWidth / 2 + 3;
        this.xScalePaddingLeft = (firstWidth / 2 > this.yLabelWidth + 10) ? firstWidth / 2 : this.yLabelWidth + 10;

        this.xLabelRotation = 0;
        if (this.display) {
            var originalLabelWidth = helpers.longestText(this.ctx, this.font, this.xLabels),
                cosRotation,
                firstRotatedWidth;
            this.xLabelWidth = originalLabelWidth;
            //Allow 3 pixels x2 padding either side for label readability
            var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;
            //check if option is set if so use that
            if (this.overrideRotation) {
                // do the same as before but manualy set the rotation rather than looping
                 this.xLabelRotation = this.overrideRotation;
                 cosRotation = Math.cos(helpers.radians(this.xLabelRotation));
                  // We're right aligning the text now.
                    if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8) {
                        this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
                    }
                    this.xScalePaddingRight = this.fontSize / 2;
                    this.xLabelWidth = cosRotation * originalLabelWidth;
            } else {
                //Max label rotate should be 90 - also act as a loop counter
                while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)) {
                    cosRotation = Math.cos(helpers.radians(this.xLabelRotation));

                    firstRotated = cosRotation * firstWidth;
                    lastRotated = cosRotation * lastWidth;

                    // We're right aligning the text now.
                    if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8) {
                        this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
                    }
                    this.xScalePaddingRight = this.fontSize / 2;


                    this.xLabelRotation++;
                    this.xLabelWidth = cosRotation * originalLabelWidth;

                }
            }
            if (this.xLabelRotation > 0) {
                this.endPoint -= Math.sin(helpers.radians(this.xLabelRotation)) * originalLabelWidth + 3;
            }
        } else {
            this.xLabelWidth = 0;
            this.xScalePaddingRight = this.padding;
            this.xScalePaddingLeft = this.padding;
        }

    },

});

然后在扩展条形类中创建一个新的图形类型并重写init方法来使用新的

then in the extend the bar class to create a new graph type and override the init method to use the new

Chart.types.Bar.extend({
    name: "MyBar",
    initialize: function(data) {

        //Expose options as a scope variable here so we can access it in the ScaleClass
        var options = this.options;

        this.ScaleClass = Chart.MyScale.extend({
            overrideRotation: options.overrideRotation,
            offsetGridLines: true,
            calculateBarX: function(datasetCount, datasetIndex, barIndex) {
                //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
                var xWidth = this.calculateBaseWidth(),
                    xAbsolute = this.calculateX(barIndex) - (xWidth / 2),
                    barWidth = this.calculateBarWidth(datasetCount);

                return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth / 2;
            },
            calculateBaseWidth: function() {
                return (this.calculateX(1) - this.calculateX(0)) - (2 * options.barValueSpacing);
            },
            calculateBarWidth: function(datasetCount) {
                //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
                var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);

                return (baseWidth / datasetCount);
            }
        });

        this.datasets = [];

        //Set up tooltip events on the chart
        if (this.options.showTooltips) {
            helpers.bindEvents(this, this.options.tooltipEvents, function(evt) {
                var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];

                this.eachBars(function(bar) {
                    bar.restore(['fillColor', 'strokeColor']);
                });
                helpers.each(activeBars, function(activeBar) {
                    activeBar.fillColor = activeBar.highlightFill;
                    activeBar.strokeColor = activeBar.highlightStroke;
                });
                this.showTooltip(activeBars);
            });
        }

        //Declare the extension of the default point, to cater for the options passed in to the constructor
        this.BarClass = Chart.Rectangle.extend({
            strokeWidth: this.options.barStrokeWidth,
            showStroke: this.options.barShowStroke,
            ctx: this.chart.ctx
        });

        //Iterate through each of the datasets, and build this into a property of the chart
        helpers.each(data.datasets, function(dataset, datasetIndex) {

            var datasetObject = {
                label: dataset.label || null,
                fillColor: dataset.fillColor,
                strokeColor: dataset.strokeColor,
                bars: []
            };

            this.datasets.push(datasetObject);

            helpers.each(dataset.data, function(dataPoint, index) {
                //Add a new point for each piece of data, passing any required data to draw.
                datasetObject.bars.push(new this.BarClass({
                    value: dataPoint,
                    label: data.labels[index],
                    datasetLabel: dataset.label,
                    strokeColor: dataset.strokeColor,
                    fillColor: dataset.fillColor,
                    highlightFill: dataset.highlightFill || dataset.fillColor,
                    highlightStroke: dataset.highlightStroke || dataset.strokeColor
                }));
            }, this);

        }, this);

        this.buildScale(data.labels);

        this.BarClass.prototype.base = this.scale.endPoint;

        this.eachBars(function(bar, index, datasetIndex) {
            helpers.extend(bar, {
                width: this.scale.calculateBarWidth(this.datasets.length),
                x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
                y: this.scale.endPoint
            });
            bar.save();
        }, this);

        this.render();
    },
});

现在您可以使用此图表类型声明图表并传入选项 overrideRotation

now you can declare a chart using this chart type and pass in the option overrideRotation

这是一个小提琴示例http://jsfiddle.net/leighking2/ye3usuhu/

和一个片段

var helpers = Chart.helpers;
Chart.MyScale = Chart.Scale.extend({
    calculateXLabelRotation: function() {
        //Get the width of each grid by calculating the difference
        //between x offsets between 0 and 1.

        this.ctx.font = this.font;

        var firstWidth = this.ctx.measureText(this.xLabels[0]).width,
            lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,
            firstRotated,
            lastRotated;


        this.xScalePaddingRight = lastWidth / 2 + 3;
        this.xScalePaddingLeft = (firstWidth / 2 > this.yLabelWidth + 10) ? firstWidth / 2 : this.yLabelWidth + 10;

        this.xLabelRotation = 0;
        if (this.display) {
            var originalLabelWidth = helpers.longestText(this.ctx, this.font, this.xLabels),
                cosRotation,
                firstRotatedWidth;
            this.xLabelWidth = originalLabelWidth;
            //Allow 3 pixels x2 padding either side for label readability
            var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;
            
            if (this.overrideRotation) {
                 this.xLabelRotation = this.overrideRotation;
                 cosRotation = Math.cos(helpers.radians(this.xLabelRotation));
                  // We're right aligning the text now.
                    if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8) {
                        this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
                    }
                    this.xScalePaddingRight = this.fontSize / 2;
                    this.xLabelWidth = cosRotation * originalLabelWidth;
            } else {
                //Max label rotate should be 90 - also act as a loop counter
                while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)) {
                    cosRotation = Math.cos(helpers.radians(this.xLabelRotation));

                    firstRotated = cosRotation * firstWidth;
                    lastRotated = cosRotation * lastWidth;

                    // We're right aligning the text now.
                    if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8) {
                        this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
                    }
                    this.xScalePaddingRight = this.fontSize / 2;


                    this.xLabelRotation++;
                    this.xLabelWidth = cosRotation * originalLabelWidth;

                }
            }
            if (this.xLabelRotation > 0) {
                this.endPoint -= Math.sin(helpers.radians(this.xLabelRotation)) * originalLabelWidth + 3;
            }
        } else {
            this.xLabelWidth = 0;
            this.xScalePaddingRight = this.padding;
            this.xScalePaddingLeft = this.padding;
        }

    },

});

Chart.types.Bar.extend({
    name: "MyBar",
    initialize: function(data) {

        //Expose options as a scope variable here so we can access it in the ScaleClass
        var options = this.options;

        this.ScaleClass = Chart.MyScale.extend({
            overrideRotation: options.overrideRotation,
            offsetGridLines: true,
            calculateBarX: function(datasetCount, datasetIndex, barIndex) {
                //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
                var xWidth = this.calculateBaseWidth(),
                    xAbsolute = this.calculateX(barIndex) - (xWidth / 2),
                    barWidth = this.calculateBarWidth(datasetCount);

                return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth / 2;
            },
            calculateBaseWidth: function() {
                return (this.calculateX(1) - this.calculateX(0)) - (2 * options.barValueSpacing);
            },
            calculateBarWidth: function(datasetCount) {
                //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
                var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);

                return (baseWidth / datasetCount);
            }
        });

        this.datasets = [];

        //Set up tooltip events on the chart
        if (this.options.showTooltips) {
            helpers.bindEvents(this, this.options.tooltipEvents, function(evt) {
                var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];

                this.eachBars(function(bar) {
                    bar.restore(['fillColor', 'strokeColor']);
                });
                helpers.each(activeBars, function(activeBar) {
                    activeBar.fillColor = activeBar.highlightFill;
                    activeBar.strokeColor = activeBar.highlightStroke;
                });
                this.showTooltip(activeBars);
            });
        }

        //Declare the extension of the default point, to cater for the options passed in to the constructor
        this.BarClass = Chart.Rectangle.extend({
            strokeWidth: this.options.barStrokeWidth,
            showStroke: this.options.barShowStroke,
            ctx: this.chart.ctx
        });

        //Iterate through each of the datasets, and build this into a property of the chart
        helpers.each(data.datasets, function(dataset, datasetIndex) {

            var datasetObject = {
                label: dataset.label || null,
                fillColor: dataset.fillColor,
                strokeColor: dataset.strokeColor,
                bars: []
            };

            this.datasets.push(datasetObject);

            helpers.each(dataset.data, function(dataPoint, index) {
                //Add a new point for each piece of data, passing any required data to draw.
                datasetObject.bars.push(new this.BarClass({
                    value: dataPoint,
                    label: data.labels[index],
                    datasetLabel: dataset.label,
                    strokeColor: dataset.strokeColor,
                    fillColor: dataset.fillColor,
                    highlightFill: dataset.highlightFill || dataset.fillColor,
                    highlightStroke: dataset.highlightStroke || dataset.strokeColor
                }));
            }, this);

        }, this);

        this.buildScale(data.labels);

        this.BarClass.prototype.base = this.scale.endPoint;

        this.eachBars(function(bar, index, datasetIndex) {
            helpers.extend(bar, {
                width: this.scale.calculateBarWidth(this.datasets.length),
                x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
                y: this.scale.endPoint
            });
            bar.save();
        }, this);

        this.render();
    },
});



var randomScalingFactor = function() {
    return Math.round(Math.random() * 100)
};

var barChartData = {
    labels: ["January", "February", "March", "April", "May", "June", "July"],
    datasets: [{
        fillColor: "rgba(220,220,220,0.5)",
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
    }, {
        fillColor: "rgba(151,187,205,0.5)",
        strokeColor: "rgba(151,187,205,0.8)",
        highlightFill: "rgba(151,187,205,0.75)",
        highlightStroke: "rgba(151,187,205,1)",
        data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
    }, {
        fillColor: "rgba(15,18,20,0.5)",
        strokeColor: "rgba(15,18,20,0.8)",
        highlightFill: "rgba(15,18,20,0.75)",
        highlightStroke: "rgba(15,18,20,1)",
        data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
    }]

}
window.onload = function() {
    var ctx = document.getElementById("canvas").getContext("2d");
    window.myBar = new Chart(ctx).MyBar(barChartData, {
        overrideRotation: 30
    });
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.1/Chart.js"></script>

    <canvas id="canvas" height="150" width="300"></canvas>

这篇关于Chart Js 更改 Ox 轴上的文本标签方向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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