Спарклайны можно использовать для быстрой визуализации дисперсии данных. Они маленькие и интуитивно понятные.

Мы будем использовать Vue и D3 для создания небольшого спарклайна компонента с использованием Vue.js. В следующей статье я покажу вам, как использовать этот компонент для создания« приборной панели » для легкой визуализации множества точек данных.

Сначала убедитесь, что у вас установлен Vue CLI. Затем создайте новый проект.

vue create sparkboard

Интерфейс командной строки задаст вам вопросы о том, как вы хотите настроить свой проект. Вы можете принять значения по умолчанию или вручную выбрать функции, которые вам нравятся. Я выбрал вручную…

  • Вавилон
  • Линтер / Форматтер
  • ESLint + Prettier
  • Lint при сохранении
  • В специальных файлах конфигурации

После создания проекта запустите сервер разработки.

cd sparkboard
npm run serve

Создайте новый компонент в каталоге src/components с именем SparkLine.vue

<template>
  <svg viewBox="0 0 200 40">
    <path d="M 0 20 H 200"
          fill="none"
          stroke-width="3"
          stroke-color="gold" />
  </svg>
</template>
<script>
export default {
  name: "SparkLine"
}
</script>

Обратите внимание, что корневой элемент компонента - это <svg>. Это элемент, к которому мы привяжем D3 при создании диаграммы. Вы также можете видеть, что <svg> имеет viewBox из 0 0 200 40. Это дает ему размеры 200 пикселей в ширину и 40 пикселей в высоту. Фактическая ширина и высота определяются контейнером элемента, но размер 200 x 40 viewBox дает хорошее соотношение высоты к ширине для спарклайновой диаграммы.

Наконец, внутри <svg> находится <path>. Это наша настоящая линия. На данный момент это просто жестко запрограммированная идеально прямая горизонтальная линия.

Мы можем увидеть наш прогресс на данный момент, поместив наш компонент в главную App.vue. В этом файле замените все в шаблоне на…

<template>
  <div style="width: 100px">
    <SparkLine />
  </div>
</template>

Обратите внимание, как мы помещаем компонент спарклайна внутрь элемента контейнера с узкой шириной. Это придаст ему традиционный маленький вид.

Теперь замените раздел скрипта на…

<script>
import SparkLine from "./components/SparkLine.vue";
export default {
  name: "App",
  components: {
    SparkLine
  }
};
</script>

Вы можете заметить, как мы только что изменили HelloWorld на SparkLine. В остальном все то же самое.

Поскольку мы очистили шаблон, нам больше не нужны стили по умолчанию. Так что не стесняйтесь удалять все из раздела <style>.

Теперь запустите сервер разработки.

npm run serve

Когда сервер запущен, мы можем посетить http: // localhost: 8080 / и увидеть наш прогресс на данный момент.

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

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

Вернувшись к SparkLine.vue и добавив к разделу script, определите свойство с именем data. Эта опора будет массивом. Мы также скажем, чтобы он просто использовал базовый массив [0, 0], если данные не передаются.

<script>
export default {
  name: "SparkLine",
  props: {
    data: {
      type: Array,
      default() {
        return [0, 0];
      }
    }
  }
};
</script>

Мы можем передать данные в компонент обратно в App.vue следующим образом:

<SparkLine :data="[808, 1475, 1426, 1884, 1396]" />

Обратите внимание, что строка выше заменяет существующий <SparkLine />. Также обратите внимание, что это всего лишь случайные значения, которые я придумал. Не стесняйтесь использовать все, что вам нравится.

Пришло время использовать D3.js для привязки данных к строке. Сначала установите D3.

npm i d3

Затем в SparkLine.vue импортируйте его вверху раздела <script>.

import * as d3 from "d3";

Когда компонент установлен, нам нужно сообщить D3, чтобы он настроил диаграмму. Итак, под определением props добавьте функцию mounted().

export default {
  name: "SparkLine",
  props: { /* ... snip ... */ },
  mounted() {
    // We will set up the chart here
  }
};

Внутри функции mounted() сообщите D3, куда пойдет наш график.

this.chart = d3.select("svg"); // Targets the (only) SVG element

Теперь нам нужно настроить шкалы x и y. Ось x будет начинаться в самом начале (0) нашей диаграммы и заканчиваться в самом конце (справа) нашей диаграммы (200).

this.x = d3.scaleLinear().range([0, 200]);

Ось Y будет начинаться внизу (40) и заканчиваться вверху (0) нашей диаграммы.

this.y = d3.scaleLinear().range([40, 0]);

Если вы раньше использовали шкалы D3, возможно, вам интересно, почему мы не устанавливаем здесь домен. Это потому, что мы собираемся поместить эту логику в отдельную функцию, которую можно будет вызывать в любое время при изменении наших данных.

Теперь мы должны определить функцию линии.

this.line = d3
  .line()
  .x((d, i) => this.x(i))
  .y(d => this.y(d));

Приведенный выше код определяет строку D3, где значение x определяется положением данных в массиве, а значение y определяется самой точкой данных.

Наконец, давайте вызовем метод для построения графика данных.

this.plot();

Функция, вызываемая в строке выше, пока не существует. Давай создадим это сейчас.

Это войдет в наши компоненты methods.

export default {
  name: "SparkLine",
  props: { /* ... snip ... */ },
  methods: {
    plot() {
      // Plotting code goes here
    }
  },
  mounted() { /* ... snip ... /* }
};

Первое, что нужно сделать внутри plot(), - это установить домен наших весов в соответствии с данными.

this.x.domain([0, this.data.length - 1]);
this.y.domain(d3.extent(this.data));

Как вы можете видеть выше, область шкалы x начинается с 0 и заканчивается в конце массива. Область шкалы y начинается с наименьшего значения данных и заканчивается наибольшим.

Теперь собственно скорректируем линию диаграммы. Также в plot():

this.chart.select("path").attr("d", this.line(this.data));

Если вы сохраните SparkLine.vue и снова посмотрите на http: // localhost: 8080 / (при условии, что сервер разработки все еще работает), вы увидите спарклайн!

Что произойдет, если наши данные изменятся? Все, что нам нужно сделать, это снова вызвать метод plot(). Настройте наблюдателя для этого. Этот наблюдатель будет «наблюдать» за свойством data и вызывать plot() каждый раз, когда оно изменяется.

export default {
  name: "SparkLine",
  props: { /* ... snip ... */ },
  watch: {
    data() {
      this.plot();
    }
  },
  methods: { /* ... snip ... /* },
  mounted() { /* ... snip ... /* }
};

И теперь наш компонент может реагировать на изменение данных!

Хотя все это работает как единый компонент, есть одна важная ошибка, которую мы должны исправить, если мы хотим повторно использовать этот компонент более одного раза на одной странице. Прямо сейчас у нас есть D3, выбирающий единственный элемент <svg> на странице. Если у вас более одного <svg> на одной странице, D3 просто выберет первый найденный. Это нехорошо. Мы хотим выбрать <svg> в этом компоненте.

Для этого мы можем присвоить нашему <svg> уникальный идентификатор.

Сначала установите наноид.

npm i nanoid

Импортируйте его в наш компонент в верхней части раздела <script>.

import { nanoid } from "nanoid";

Создайте новое свойство данных id и используйте наноид, чтобы сделать его случайным.

export default {
  name: "SparkLine",
  props: { /* ... snip ... /* },
  data() {
    return {
      id: `chart-${nanoid()}`
    };
  },
  methods: { /* ... snip ... /*},
  mounted() { /* ... snip ... /*}
};

Мы используем строку шаблона `chart-${nanoid()}`, чтобы наш случайный идентификатор был, например, в формате chart-kHM_8K1yz8GGq6MVBwfoG или chart-VG5J13fYZIdMBrSDRuEBX. Это всегда случайно.

В шаблоне установите для <svg> id этот новый идентификатор.

<svg :id="id" viewBox="0 0 200 40">

Наконец, скажите D3 выбрать элемент на основе этого идентификатора.

Заменять

this.chart = d3.select("svg");

с участием

this.chart = d3.select(`#${this.id}`);

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

<template>
  <div style="width:100px">
    <SparkLine :data="[808, 1475, 1426, 1884, 1396]" />
    <SparkLine :data="[3246, 1941, 2649, 1633, 1262]" />
    <SparkLine :data="[190, 128, 209, 208, 116]" />
  </div>
</template>

Весь код для этой статьи имеет открытый исходный код и опубликован на GitHub.



В следующей статье я покажу вам, как использовать этот компонент для создания« приборной панели » для легкой визуализации множества точек данных.

Упражнение для читателя

Компонент жестко запрограммирован на наличие желтой линии. Что, если вы хотите иметь возможность устанавливать цвет индивидуально для каждого компонента? Подсказка: используйте prop (и не забудьте установить значение по умолчанию!).