Chart.js: evenly distribute ticks when using maxTicksLimit

前端 未结 2 409
清酒与你
清酒与你 2020-12-08 22:07

I made a line chart using Chart.js version 2.1.3.

        var canvas = $(\'#gold_chart\').get(0);
        var ctx = canvas.getContext(\'2d\');
        var f         


        
2条回答
  •  感情败类
    2020-12-08 22:54

    Chart.js uses an integral skipRatio (to figure out how many labels to skip). With Chart.js v2.1.x, you can write your own plugin to use a fractional skipRatio


    Preview


    Script

    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);
                    }
                };
            }
        },
    });
    

    Fiddle - http://jsfiddle.net/bh63pe1v/

提交回复
热议问题