简体   繁体   English

具有偏移的Chartjs折线图数据集

[英]Chartjs line graph dataset with offset

How would one enter datasets with an offset into Chart.js, so first x values will not get drawn? 如何输入具有Chart.js偏移量的数据集,因此首先不会绘制x值? eg 例如 在此输入图像描述

I cannot seem to wrap my head around it :/ 我好像无法绕过它:/

The below answer is for chartjs version 1.x 以下答案适用于chartjs版本1.x.

One way can be to create a custom graph that will allow for null values, in a previous question i answered i applied the same technique but it can also be used here. 一种方法是创建一个允许空值的自定义图形,在前一个问题中我回答我应用了相同的技术,但它也可以在这里使用。

In my answer, i explain how i have achieved the gaps https://stackoverflow.com/a/25319120/2737978 在我的回答中,我解释了我是如何实现差距的https://stackoverflow.com/a/25319120/2737978

The only difference here is rather than having gaps in 1 datasets data, the gaps can be used to create your desired effect. 这里唯一的区别是不是在1个数据集数据中存在间隙,而是可以使用间隙来创建所需的效果。

When setting up your data just make sure the two datasets lineup with the labels like so, 在设置数据时,请确保两个数据集的阵容与标签一样,

//labels that will applied to both datasets
labels: ["January", "February", "March", "April", "May", "June", "July"],

//data sets will lineup to the labels
data: [65, 34, 21, null, null, null, null]
data: [null, null, 88, 19, 86, 27, 90]

fiddle http://jsfiddle.net/leighking2/yoqfwt8o/ 小提琴http://jsfiddle.net/leighking2/yoqfwt8o/

the extend line graph 延长线图

 Chart.types.Line.extend({
        // Passing in a name registers this chart in the Chart namespace in the same way
        name: "MissingLine",
        initialize: function(data) {
            var helpers = Chart.helpers;
            //Declare the extension of the default point, to cater for the options passed in to the constructor
            this.PointClass = Chart.Point.extend({
                strokeWidth: this.options.pointDotStrokeWidth,
                radius: this.options.pointDotRadius,
                display: this.options.pointDot,
                hitDetectionRadius: this.options.pointHitDetectionRadius,
                ctx: this.chart.ctx,
                inRange: function(mouseX) {
                    return (Math.pow(mouseX - this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius, 2));
                }
            });

            this.datasets = [];

            //Set up tooltip events on the chart
            if (this.options.showTooltips) {
                helpers.bindEvents(this, this.options.tooltipEvents, function(evt) {
                    var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
                    this.eachPoints(function(point) {
                        point.restore(['fillColor', 'strokeColor']);
                    });
                    helpers.each(activePoints, function(activePoint) {
                        activePoint.fillColor = activePoint.highlightFill;
                        activePoint.strokeColor = activePoint.highlightStroke;
                    });
                    this.showTooltip(activePoints);
                });
            }

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

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

                this.datasets.push(datasetObject);


                helpers.each(dataset.data, function(dataPoint, index) {
                    /**
                     *
                     * Check for datapoints that are null
                     */
                    if (helpers.isNumber(dataPoint) || dataPoint === null) {
                        //Add a new point for each piece of data, passing any required data to draw.
                        datasetObject.points.push(new this.PointClass({
                            /**
                             * add ignore field so we can skip them later
                             *
                             */
                            ignore: dataPoint === null,
                            value: dataPoint,
                            label: data.labels[index],
                            datasetLabel: dataset.label,
                            strokeColor: dataset.pointStrokeColor,
                            fillColor: dataset.pointColor,
                            highlightFill: dataset.pointHighlightFill || dataset.pointColor,
                            highlightStroke: dataset.pointHighlightStroke || dataset.pointStrokeColor
                        }));
                    }
                }, this);

                this.buildScale(data.labels);


                this.eachPoints(function(point, index) {
                    helpers.extend(point, {
                        x: this.scale.calculateX(index),
                        y: this.scale.endPoint
                    });
                    point.save();
                }, this);

            }, this);


            this.render();
        },

        draw: function(ease) {
            var helpers = Chart.helpers;
            var easingDecimal = ease || 1;
            this.clear();

            var ctx = this.chart.ctx;

            this.scale.draw(easingDecimal);


            helpers.each(this.datasets, function(dataset) {

                //Transition each point first so that the line and point drawing isn't out of sync
                //We can use this extra loop to calculate the control points of this dataset also in this loop

                helpers.each(dataset.points, function(point, index) {
                    point.transition({
                        y: this.scale.calculateY(point.value),
                        x: this.scale.calculateX(index)
                    }, easingDecimal);

                }, this);


                // Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
                // This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
                if (this.options.bezierCurve) {
                    helpers.each(dataset.points, function(point, index) {
                        //If we're at the start or end, we don't have a previous/next point
                        //By setting the tension to 0 here, the curve will transition to straight at the end
                        if (index === 0) {
                            point.controlPoints = helpers.splineCurve(point, point, dataset.points[index + 1], 0);
                        } else if (index >= dataset.points.length - 1) {
                            point.controlPoints = helpers.splineCurve(dataset.points[index - 1], point, point, 0);
                        } else {
                            point.controlPoints = helpers.splineCurve(dataset.points[index - 1], point, dataset.points[index + 1], this.options.bezierCurveTension);
                        }
                    }, this);
                }


                //Draw the line between all the points
                ctx.lineWidth = this.options.datasetStrokeWidth;
                ctx.strokeStyle = dataset.strokeColor;


                var penDown = false;
                var start = null

                helpers.each(dataset.points, function(point, index) {

                    /**
                     * no longer draw if the last point was ignore (as we don;t have anything to draw from)
                     * or if this point is ignore
                     * or if it's the first
                     */
                    if (!point.ignore && !penDown) {
                        ctx.beginPath();
                        penDown = true;
                        start = point;
                    }
                    if (index > 0 && !dataset.points[index - 1].ignore && !point.ignore) {
                        if (this.options.bezierCurve) {
                            ctx.bezierCurveTo(
                                dataset.points[index - 1].controlPoints.outer.x,
                                dataset.points[index - 1].controlPoints.outer.y,
                                point.controlPoints.inner.x,
                                point.controlPoints.inner.y,
                                point.x,
                                point.y
                            );
                        } else {
                            ctx.lineTo(point.x, point.y);
                        }

                    } else if (index === 0 || dataset.points[index - 1].ignore) {
                        ctx.moveTo(point.x, point.y);
                    }

                    if (((dataset.points.length > index + 1 && dataset.points[index + 1].ignore) ||
                        dataset.points.length == index + 1) && !point.ignore) {
                        ctx.stroke();

                        if (this.options.datasetFill) {
                            ctx.lineTo(point.x, this.scale.endPoint);
                            ctx.lineTo(start.x, this.scale.endPoint);
                            ctx.fillStyle = dataset.fillColor;
                            ctx.closePath();
                            if (point.x != start.x) {
                                ctx.fill();
                            }
                        }
                        penDown = false;
                    }

                }, this);


                //Now draw the points over the line
                //A little inefficient double looping, but better than the line
                //lagging behind the point positions
                helpers.each(dataset.points, function(point) {
                    /**
                     * don't draw the dot if we are ignoring
                     */
                    if (!point.ignore)
                        point.draw();
                });

            }, this);
        }
    });

then to use 然后使用

var ctx = document.getElementById("chart").getContext("2d");
    var data = {
        labels: ["January", "February", "March", "April", "May", "June", "July"],
        datasets: [{
                label: "My First dataset",
                fillColor: "rgba(220,220,220,0.2)",
                strokeColor: "rgba(220,220,220,1)",
                pointColor: "rgba(220,220,220,1)",
                pointStrokeColor: "#fff",
                pointHighlightFill: "#fff",
                pointHighlightStroke: "rgba(220,220,220,1)",
                data: [65, 34, 21, null, null, null, null]
            },
            {
            label: "My Second dataset",
            fillColor: "rgba(151,187,205,0.2)",
            strokeColor: "rgba(151,187,205,1)",
            pointColor: "rgba(151,187,205,1)",
            pointStrokeColor: "#fff",
            pointHighlightFill: "#fff",
            pointHighlightStroke: "rgba(151,187,205,1)",
            data: [null, null, 88, 19, 86, 27, 90]
        }



        ]
    };
var myLineChart = new Chart(ctx).MissingLine(data);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM