Как относительно растянуть две серии с разным количеством индексов в одном графике с помощью чартиста js? - PullRequest
0 голосов
/ 23 октября 2018

Prelude

Использование Chartist Я знаю, что есть возможность «заполнить дыры» в двух разных наборах данных, которые не имеют эквивалентного количества элементов, как в следующем примере:

var chart = new Chartist.Line('.ct-chart', {
  labels: [1, 2, 3, 4, 5, 6, 7],
  series: [
    [5, 5, 10, 8, 7, 5, 4],
    [10, 15, null, 12, null, null, null]
  ]
}, {
  lineSmooth: Chartist.Interpolation.cardinal({
    fillHoles: true,
  })
});
<script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
<link href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css" rel="stylesheet"/>
<div class="ct-chart"></div>

Обратите внимание, что во втором ряду будет показана только строка до последнего значения, которое не является null (при индексе 4).

Вопрос

Есть ли способ заставить чартиста сделать вторую серию относительно первой, растягивая строку второй серии, чтобы соответствовать первой до последнего значения самой длинной серии?

1 Ответ

0 голосов
/ 23 октября 2018

Вы можете написать несколько помощников, которые изменят ваши массивы данных:

  • trimNulls удаляет любые значения null из начала и конца массива:

    [10, 15, null, 12, null, null, null] -> [10, 15, null, 12]
    
  • stretch принимает массив и необходимую длину и распределяет исходные значения по новым индексам:

    [10, 15, null, 12] -> 7 -> [10, null, 15, null, null, null, 12]
    
  • alignSeries принимает списокряд данных и выравнивает каждый из них к самому широкому.

    [ [ 1, 2, 3, 4], [1, 4], [null, 1, 4] ] -> 
      [ [ 1, 2, 3, 4], [1, null, null, 4], [1, null, null, 4] ]
    

В рабочем примере со старой строкой, включенной для справки:

const trimNulls = (data) => {
  // Find the first non-null value
  const start = data.findIndex(y => y !== null);
  // Find the last non-null value
  const end = data.length - Array.from(data).reverse()
                                 .findIndex(y => y !== null);
  // Return the elements between those boundaries                               
  return data.slice(start, end);
}

const stretch = (data, newLength) => {
  // Create array of required number of nulls
  const stretched = Array(newLength).fill(null);
  // Determine the stretch factor
  const s = newLength / data.length;
  // For every value we want to keep, place it
  // at its new, stretched index
  data.forEach((y, x) => {
    stretched[Math.ceil(x * s)] = y;
  });
  // Return the newly created array
  return stretched;
}

// Takes a list of series and aligns their starts and ends, stretching 
// in between
const alignSeries = series => {
  // Trim each series
  const trimmed = series.map(trimNulls);
  // Find the longest one
  const maxLength = Math.max(...trimmed.map(t => t.length));
  // Stretch all series to the longest length and return
  return trimmed.map(t => stretch(t, maxLength));
};

var chart = new Chartist.Line('.ct-chart', {
  labels: [1, 2, 3, 4, 5, 6, 7],
  series: [
    ...alignSeries([
      [5, 5, 10, 8, 7, 5, 4],
      [10, 15, null, 12, null, null, null]
    ]),
    // For reference
    [10, 15, null, 12, null, null, null]
  ]
}, {
  lineSmooth: Chartist.Interpolation.cardinal({
    fillHoles: true,
  })
});
<script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
<link href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css" rel="stylesheet"/>
<div class="ct-chart"></div>
...