不使用chart.js绘制空值

时间:2015-12-29 17:48:07

标签: chart.js

我使用Chart.js绘制图表.. 我的数据集有一些空值, 实际上,chart.js以这种方式绘制了空值之前和之后的点之间的一条线:

enter image description here

红色箭头表示空值的位置

我想找到如何不绘制这些空值 enter image description here

我使用的配置很简单:

# Take many values at once rather than reading each individually
end_num = sh.UsedRange.Rows.Count
col_a = sh.Range(xl.Cells(1, 1), xl.Cells(end_num, 1)).Value

# The magic numbers to turn calculation on and off
xlCalculationManual = -4135
xlCalculationAutomatic = -4105

# Turn calculation to manual
xl.Calculation = xlCalculationManual

# Turn screen updating off
xl.ScreenUpdating = False

# RUN YOUR CODE HERE #

# Turn things back on when done
xl.ScreenUpdating = True
xl.Calculation = xlCalculationAutomatic

感谢您的帮助

5 个答案:

答案 0 :(得分:20)

如果您仍然访问此页面,则新版本支持跳过丢失的数据。 。 如果希望通过跳过缺失数据来连接线路,可以在选项中设置spanGaps:true。

然后,如果您有缺少数据的null或NaN,它将跳过它并连接到下一个点。

.....
 showTooltips: true,
        options: {
             spanGaps: true,
  ......

Documentation here

答案 1 :(得分:7)

我知道这已经很老了,但我认为现在有一个更好的解决方案。用Number.NaN

替换所有空值

http://www.chartjs.org/docs/#line-chart-chart-options

下面是我用红线上的NaN替换的数据点

Broken Line

答案 2 :(得分:5)

使用Chart.js打破(破碎)行

您可以扩展折线图类型以执行此操作

预览

enter image description here

<强>脚本

(frame-parameter FRAME 'cursor-color)

然后

Chart.types.Line.extend({
  name: "LineAlt",
  initialize: function (data) {
    var fillColors = [];
    var strokeColors = [];
    data.datasets.forEach(function (dataset, i) {
      if (dataset.data.indexOf(null) !== -1) {
        fillColors.push(dataset.fillColor);
        strokeColors.push(dataset.strokeColor);
        dataset.fillColor = "rgba(0,0,0,0)"
        dataset.strokeColor = "rgba(0,0,0,0)"
      }
    })

    Chart.types.Line.prototype.initialize.apply(this, arguments);

    var self = this;
    data.datasets.forEach(function (dataset, i) {
      if (dataset.data.indexOf(null) !== -1) {
        self.datasets[i]._saved = {
          fillColor: fillColors.shift(),
          strokeColor: strokeColors.shift()
        }
      }
    })
  },
  draw: function () {
    Chart.types.Line.prototype.draw.apply(this, arguments);

    // from Chart.js library code
    var hasValue = function (point) {
      return point.value !== null;
    },
    nextPoint = function (point, collection, index) {
      return Chart.helpers.findNextWhere(collection, hasValue, index) || point;
    },
    previousPoint = function (point, collection, index) {
      return Chart.helpers.findPreviousWhere(collection, hasValue, index) || point;
    };

    var ctx = this.chart.ctx;
    var self = this;
    ctx.save();
    this.datasets.forEach(function (dataset) {
      if (dataset._saved) {
        ctx.lineWidth = self.options.datasetStrokeWidth;
        ctx.strokeStyle = dataset._saved.strokeColor;
        ctx.fillStyle = dataset._saved.fillColor;

        // adapted from Chart.js library code
        var pointsWithValues = Chart.helpers.where(dataset.points, hasValue);
        dataset.points.forEach(function (point, index) {
          if (index === 0 || (hasValue(point) && !hasValue(dataset.points[index - 1])))
            point.start = true;
        });
        var currentStartPoint = undefined;
        Chart.helpers.each(pointsWithValues, function (point, index) {
          if (point.start) {
            if (currentStartPoint) {
              ctx.lineTo(pointsWithValues[index - 1].x, self.scale.endPoint);
              ctx.lineTo(currentStartPoint.x, self.scale.endPoint);
              ctx.closePath();
              ctx.fill();
            }

            currentStartPoint = point;
            ctx.beginPath();
            ctx.moveTo(point.x, point.y);
          }
          else {
            if (self.options.bezierCurve) {
              var previous = previousPoint(point, pointsWithValues, index);
              ctx.bezierCurveTo(
                previous.controlPoints.outer.x,
                previous.controlPoints.outer.y,
                point.controlPoints.inner.x,
                point.controlPoints.inner.y,
                point.x,
                point.y
              );
            }
            else {
              ctx.lineTo(point.x, point.y);
            }
          }

          ctx.stroke();
        }, this);

        ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, self.scale.endPoint);
        ctx.lineTo(currentStartPoint.x, self.scale.endPoint);
        ctx.closePath();
        ctx.fill();
      }
    })

    ctx.restore();
  }
});

小提琴 - https://jsfiddle.net/hbrhz2q4/

答案 3 :(得分:1)

我不确定ChartJS本身是否可以原生这样做。

然而,我做过类似事情的一种方法是用多个数据集制作线图。当达到空值时,一个数据集将结束,并且下一个数据集将开始。这当然需要在将所有这些数据传递到var linechartdata

之前解析所有这些数据

您可以使所有数据集具有相同的颜色和高光,并且图形应使用空格进行渲染,其中将找到空数据。

答案 4 :(得分:0)

您可以使用ChartNew.js并且如果您希望未链接缺失值之间的点,请设置选项&#34; extrapolateMissingData:false&#34;。这对我有用。