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

Для нашего финального проекта в Fullstack Academy в Чикаго моей команде, завершившей цикл, нужно было включить набор визуализаций данных в наше сатирическое приложение для геймифицированного фондового рынка, и мы решили найти подходящую библиотеку, чтобы помочь.

После некоторых начальных экспериментов с D3 мы решили попробовать что-то, что будет лучше работать с React, и мы настоятельно рекомендовали пакет Victory Chart от Formidable (он используется Nate Silver’s 538 и другими крупными новостными организациями).

Библиотека Victory невероятно проста в использовании и очень модульна. И документы неплохие, хотя кое-где и немного расплывчаты. Если вы знаете React, это будет вам очень знакомо. Вот как сделать базовую линейную диаграмму:

<VictoryChart data={basicData} height={250}>
  <VictoryLine 
    interpolation=”linear” 
    data={basicData} 
    x={x} y={y} 
    style={{data: {stroke: ‘#c43a31’, strokeWidth: 1}}}
  />
</VictoryChart>

Вот основные данные, которые мы ему передаем.

const basicData = [{x: 0, y: 2}, {x: 1, y: 2.5}, {x: 2, y: 4}, {x: 3, y: 5}, {x: 4, y: 3}, {x: 5, y: 1}, {x: 6, y: 3}]

А вот как выглядит линейный график:

Довольно круто! Теперь, если вы хотите, чтобы отдельные узлы были более заметными, просто добавьте <VictoryScatter /> либо до, либо после (или вместо!) <VictoryLine />. (Примечание: если первым будет упорядочен <VictoryLine />, то узлы разброса будут отображаться поверх строк; в противном случае верно обратное.) Вот два вместе:

А вот код для узлов разброса, который в данном случае был перед <VictoryLine />:

<VictoryScatter 
  style={{data: {fill: 'green'}}}
  size={7} 
  data={basicData} 
/>

Хорошо, но что, если у вас много точек данных и хронологическая ось x с множеством неравномерно упорядоченных дат, и вы не хотите, чтобы метки дат перекрывали друг друга, и вы хотите, чтобы иметь возможность увеличивать масштаб диаграммы до бесконечно детализированного уровня, и вы хотите, чтобы даты автоматически анализировали себя? Что ж, вы можете это сделать, и в документации Victory это даже кажется простым. Но есть пара вещей, о которых они вам не говорят, поэтому ваши диаграммы будут выглядеть примерно так:

Ой. Ну обо всем по порядку. После того, как вы вызвали все свои данные из API, вы захотите переформатировать их так, чтобы они представляли собой массив из {x: date, y: price} объектов. Victory также позволит вам указать эти данные так:

<VictoryChart data={basicData} height={250}>
  <VictoryLine 
    interpolation=”linear” 
    data={basicData} 
    x="basicData.date" y="basicData.price"
    style={{data: {stroke: ‘#c43a31’, strokeWidth: 1}}}
  />
</VictoryChart>

Затем, если вы имеете дело с датами, вам нужно превратить их в настоящие объекты Javascript Date с помощью конструктора new Date (). Помните, что эта конструкция теряется, когда данные поступают из вашего API, поскольку все, что вы получаете, - это набор объектов JSON. Чтобы JS и Victory могли распознать даты, какими они являются, вам потребуется их повторно создать. (Между прочим, если вы не знакомы с объектом JS Date, вот хорошая, обстоятельная статья об этом).

Вы, вероятно, проделаете всю эту процедуру в несколько громоздком Redux Selector, который находится в самом низу вашего магазина. Это будет выглядеть примерно так:

export const getSingleStockChart = (state, stockId) => {
  return state.transactions.allIds.reduce((result, transId) => {
    if (state.transactions.byId[transId].stockId == stockId)
      result.push({
        x: new Date(state.transactions.byId[transId].seedDate),
        y: state.transactions.byId[transId].price
      })
    return result
  }, [])
}

Если вас пугает синтаксис глубоко вложенных объектов, не беспокойтесь, единственная действительно важная часть - это то, что вы возвращаете массив, в котором объект даты объявлен как новый экземпляр объекта JS Date (т.е. new Date («2018–08 –13T17: 34: 28.779Z ”)).

Как только вы это сделаете, Победа будет творит все виды магии!

Объедините этот подход с <VictoryZoomContainer />, базовой handleZoom() функцией и разумной функцией по умолчанию state.zoomDomain, и вперед в гонки! О, еще одна вещь: убедитесь, что вы передали scale в качестве реквизита для своего <VictoryChart/>, например: scale={{x: ‘time’}}. Это ваш сигнал к Победе, чтобы узнать ваши объекты Date такими, какие они есть на самом деле.

Надеюсь, это поможет вам избежать некоторых ловушек, которые у меня были. Как только наш проект будет запущен, я постараюсь вернуться и опубликовать масштабируемые и правильно датированные диаграммы. А пока ознакомьтесь с соответствующими Документами о победе.

Спасибо замечательным людям из Formidable за создание такой замечательной библиотеки! Не стесняйтесь оставлять комментарии, если это вам помогло!