Не рисовать нулевые значения с помощью chart.js

Я использую Chart.js для рисования диаграммы. У моего набора данных есть нулевые значения, Фактически chart.js отображает линию между точками, которые являются предыдущими и преемниками нулевых значений таким образом:

введите описание изображения здесь

Красная стрелка указывает, где нулевые значения

Я хочу найти, как я могу не строить эти нулевые значения введите описание изображения здесь

Конфигурация, которую я использую, проста:

var lineChartData = {
            "datasets": [{
                "label": "defi score",
                "data": data,
                "pointStrokeColor": "#fff",
                "fillColor": "rgba(220,220,220,0.5)",
                "pointColor": "rgba(220,220,220,1)",
                "strokeColor": "rgba(220,220,220,1)",
            }],
            "labels": labels
        };


        var ctx = document.getElementById("chart_per_week").getContext("2d");
        var myLine = new Chart(ctx).Line(lineChartData, {
            responsive: true,
            scaleFontColor: "#FF5972",
            bezierCurve: false
        });

Спасибо за помощь

Ответ 1

Ломать (ломать) линии используя Chart.js

Вы можете расширить тип графика для этого


предварительный просмотр

enter image description here

скрипт

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

а потом

var data = {
    ...
    datasets: [
        {
            ...
            data: [65, 59, null, 81, 52, 62, null, 56, 40],
        }
    ],
};

...
new Chart(ctx).LineAlt(data);

Скрипка - https://jsfiddle.net/hbrhz2q4/

Ответ 2

Если вы все еще дошли до этой страницы, новая версия поддерживает пропущение отсутствующих данных., Если вы хотите, чтобы линии были подключены, пропуская отсутствующие данные, вы можете установить spanGaps: true в параметрах.

Тогда, если у вас есть null или NaN для отсутствия данных, он пропустит его и подключится к следующей точке.

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

Документация здесь

Ответ 3

Я знаю, что это довольно старый, но я думаю, что сейчас есть лучшее решение. Замените все свои нулевые значения на Number.NaN

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

Ниже приведена точка данных, которую я заменил NaN на красной строке

Сломанная линия

Ответ 4

Я не уверен, что сам ChartJS может это сделать.

Однако один из способов сделать что-то подобное - сделать линейный график из нескольких наборов данных. Один набор данных завершится, когда будет достигнуто нулевое значение, и начнется следующий набор данных. Конечно, это потребует разбора всех этих данных, прежде чем передавать их в var linechartdata​​p >

Вы можете сделать все наборы данных одинаковыми цветами и бликами, а график должен отображаться с пробелами, где были бы найдены нулевые данные.

Ответ 5

Вы можете использовать ChartNew.js. Если вы предпочитаете, чтобы точки между пропущенными значениями не были связаны, установите параметр extrapolateMissingData: false. Это сработало для меня.