Javascript Chart.js:使用maxTicksLimit时均匀分布刻度

Javascript Chart.js:使用maxTicksLimit时均匀分布刻度,javascript,chart.js,Javascript,Chart.js,我使用chart.js 2.1.3版制作了一个折线图 var canvas = $('#gold_chart').get(0); var ctx = canvas.getContext('2d'); var fillPatternGold = ctx.createLinearGradient(0, 0, 0, canvas.height); fillPatternGold.addColorStop(0, '#fdca55');

我使用chart.js 2.1.3版制作了一个折线图

        var canvas = $('#gold_chart').get(0);
        var ctx = canvas.getContext('2d');
        var fillPatternGold = ctx.createLinearGradient(0, 0, 0, canvas.height);
        fillPatternGold.addColorStop(0, '#fdca55');
        fillPatternGold.addColorStop(1, '#ffffff');

        var goldChart = new Chart(ctx, {
            type: 'line',
            animation: false,
            data: {
                labels: dates,
                datasets: [{
                    label: '',
                    data: prices,
                    pointRadius: 0,
                    borderWidth: 1,
                    borderColor: '#a97f35',
                    backgroundColor: fillPatternGold
                }]
            },
            title: {
                position: 'bottom',
                text: '\u7F8E\u5143 / \u76CE\u53F8'
            },
            options: {
                legend: {
                    display: false
                },
                tooltips: {
                    callback: function(tooltipItem) {
                        return tooltipItem.yLabel;
                    }
                },
                scales: {
                    xAxes: [{
                        ticks: {
                            maxTicksLimit: 8
                        }
                    }]
                }
            }
        });
输出如下:

如您所见,我通过
maxTicksLimit
将最大滴答数限制为8。然而,分布并不均匀。如何使蜱虫均匀分布

p、 数据集中始终有289条记录,并且每5分钟记录一次数据。
价格
变量的样本值为:

[
  {"14:10", 1280.3},
  {"14:15", 1280.25},
  {"14:20", 1282.85}
]

我尝试了不同的
maxTicksLimit
值,结果仍然不均匀。

Chart.js使用积分
skipRatio
(计算要跳过多少标签)。使用Chart.jsv2.1.x,您可以编写自己的插件来使用分数skipRatio


预览


脚本

Chart.pluginService.register({
    afterUpdate: function (chart) {
        var xScale = chart.scales['x-axis-0'];
        if (xScale.options.ticks.maxTicksLimit) {
            // store the original maxTicksLimit
            xScale.options.ticks._maxTicksLimit = xScale.options.ticks.maxTicksLimit;
            // let chart.js draw the first and last label
            xScale.options.ticks.maxTicksLimit = (xScale.ticks.length % xScale.options.ticks._maxTicksLimit === 0) ? 1 : 2;

            var originalXScaleDraw = xScale.draw
            xScale.draw = function () {
                originalXScaleDraw.apply(this, arguments);

                var xScale = chart.scales['x-axis-0'];
                if (xScale.options.ticks.maxTicksLimit) {
                    var helpers = Chart.helpers;

                    var tickFontColor = helpers.getValueOrDefault(xScale.options.ticks.fontColor, Chart.defaults.global.defaultFontColor);
                    var tickFontSize = helpers.getValueOrDefault(xScale.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
                    var tickFontStyle = helpers.getValueOrDefault(xScale.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
                    var tickFontFamily = helpers.getValueOrDefault(xScale.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
                    var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
                    var tl = xScale.options.gridLines.tickMarkLength;

                    var isRotated = xScale.labelRotation !== 0;
                    var yTickStart = xScale.top;
                    var yTickEnd = xScale.top + tl;
                    var chartArea = chart.chartArea;

                    // use the saved ticks
                    var maxTicks = xScale.options.ticks._maxTicksLimit - 1;
                    var ticksPerVisibleTick = xScale.ticks.length / maxTicks;

                    // chart.js uses an integral skipRatio - this causes all the fractional ticks to be accounted for between the last 2 labels
                    // we use a fractional skipRatio
                    var ticksCovered = 0;
                    helpers.each(xScale.ticks, function (label, index) {
                        if (index < ticksCovered)
                            return;

                        ticksCovered += ticksPerVisibleTick;

                        // chart.js has already drawn these 2
                        if (index === 0 || index === (xScale.ticks.length - 1))
                            return;

                        // copy of chart.js code
                        var xLineValue = this.getPixelForTick(index);
                        var xLabelValue = this.getPixelForTick(index, this.options.gridLines.offsetGridLines);

                        if (this.options.gridLines.display) {
                            this.ctx.lineWidth = this.options.gridLines.lineWidth;
                            this.ctx.strokeStyle = this.options.gridLines.color;

                            xLineValue += helpers.aliasPixel(this.ctx.lineWidth);

                            // Draw the label area
                            this.ctx.beginPath();

                            if (this.options.gridLines.drawTicks) {
                                this.ctx.moveTo(xLineValue, yTickStart);
                                this.ctx.lineTo(xLineValue, yTickEnd);
                            }

                            // Draw the chart area
                            if (this.options.gridLines.drawOnChartArea) {
                                this.ctx.moveTo(xLineValue, chartArea.top);
                                this.ctx.lineTo(xLineValue, chartArea.bottom);
                            }

                            // Need to stroke in the loop because we are potentially changing line widths & colours
                            this.ctx.stroke();
                        }

                        if (this.options.ticks.display) {
                            this.ctx.save();
                            this.ctx.translate(xLabelValue + this.options.ticks.labelOffset, (isRotated) ? this.top + 12 : this.options.position === "top" ? this.bottom - tl : this.top + tl);
                            this.ctx.rotate(helpers.toRadians(this.labelRotation) * -1);
                            this.ctx.font = tickLabelFont;
                            this.ctx.textAlign = (isRotated) ? "right" : "center";
                            this.ctx.textBaseline = (isRotated) ? "middle" : this.options.position === "top" ? "bottom" : "top";
                            this.ctx.fillText(label, 0, 0);
                            this.ctx.restore();
                        }
                    }, xScale);
                }
            };
        }
    },
});
Chart.pluginService.register({
更新后:功能(图表){
var xScale=图表刻度['x轴-0'];
if(xScale.options.ticks.maxTicksLimit){
//存储原始的maxTicksLimit
xScale.options.ticks.\u maxTicksLimit=xScale.options.ticks.maxTicksLimit;
//让chart.js绘制第一个和最后一个标签
xScale.options.ticks.maxTicksLimit=(xScale.ticks.length%xScale.options.ticks.\u maxTicksLimit==0)?1:2;
var originalXScaleDraw=xScale.draw
xScale.draw=函数(){
originalXScaleDraw.apply(这是参数);
var xScale=图表刻度['x轴-0'];
if(xScale.options.ticks.maxTicksLimit){
var helpers=Chart.helpers;
var tickFontColor=helpers.getValueOrDefault(xScale.options.ticks.fontColor,Chart.defaults.global.defaultFontColor);
var tickFontSize=helpers.getValueOrDefault(xScale.options.ticks.fontSize,Chart.defaults.global.defaultFontSize);
var tickFontStyle=helpers.getValueOrDefault(xScale.options.ticks.fontStyle,Chart.defaults.global.defaultFontStyle);
var tickFontFamily=helpers.getValueOrDefault(xScale.options.ticks.fontFamily,Chart.defaults.global.defaultFontFamily);
var tickLabelFont=helpers.fontString(tickFontSize、tickFontStyle、tickFontFamily);
var tl=xScale.options.gridLines.tickMarkLength;
var isRotated=xScale.labelRotation!==0;
var yTickStart=xScale.top;
var yTickEnd=xScale.top+tl;
var chartArea=chart.chartArea;
//使用保存的记号
var maxTicks=xScale.options.ticks.\u maxTicks-1;
var ticksPerVisibleTick=xScale.ticks.length/maxsticks;
//chart.js使用一个整数skipRatio-这会导致最后两个标签之间的所有小数点
//我们使用分数技巧
var ticksCovered=0;
helpers.each(xScale.ticks、函数(标签、索引){
如果(索引<勾选)
返回;
ticksCovered+=ticksPerVisibleTick;
//chart.js已经绘制了以下2个
if(index==0 | | index==(xScale.ticks.length-1))
返回;
//chart.js代码的副本
var xLineValue=this.getPixelForTick(索引);
var xLabelValue=this.getPixelForTick(索引,this.options.gridLines.offsetGridLines);
if(this.options.gridLines.display){
this.ctx.lineWidth=this.options.gridLines.lineWidth;
this.ctx.strokeStyle=this.options.gridLines.color;
xLineValue+=helpers.aliasPixel(this.ctx.lineWidth);
//绘制标签区域
this.ctx.beginPath();
if(this.options.gridLines.drawTicks){
this.ctx.moveTo(xLineValue,yTickStart);
this.ctx.lineTo(xLineValue,yTickEnd);
}
//绘制图表区域
if(this.options.gridLines.drawOnChartArea){
this.ctx.moveTo(xLineValue,chartArea.top);
这个.ctx.lineTo(xLineValue,chartArea.bottom);
}
//需要在循环中划水,因为我们可能会改变线宽和颜色
这个.ctx.stroke();
}
if(this.options.ticks.display){
这个.ctx.save();
this.ctx.translate(xLabelValue+this.options.ticks.labelOffset,(isRotated)?this.top+12:this.options.position==“top”?this.bottom-tl:this.top+tl);
this.ctx.rotate(helpers.toRadians(this.labelRotation)*-1);
this.ctx.font=tickLabelFont;
this.ctx.textAlign=(isRotated)?“右”:“中心”;
this.ctx.textBaseline=(isRotated)?“middle”:this.options.position==“top”?“bottom”:“top”;
this.ctx.fillText(标签,0,0);
这个.ctx.restore();
}
},xScale);
}
};
}
},
});


Fiddle-

一个更简单的解决方案是在
maxTicksLimit
中包含一个小数点,直到这个问题被图表永久解决

例如:

maxTicksLimit: 8,
在最后产生一个巨大的缺口

maxTicksLimit: 8.1,
最终不会产生巨大的差距

取决于你想要什么
yAxes: [{
    ticks: {
        stepSize: Math.round((Math.max.apply(Math, myListOfyValues) / 10)/5)*5,
        beginAtZero: true,
        precision: 0
    }
}]