GrChartWaterfall

Пакет: @feugene/granularity-chartsспутникГруппа: Прочее

Берут, когда движение от остатка к остатку.

Когда брать

  • движение от остатка к остатку — подписки, обязательства, склад: видно не только каждое изменение, но и то, как из начала месяца получился конец;
  • проверить, сходится ли баланс — шаги kind: 'total' ставят реальные значения на начало и на конец, и расхождение с суммой движений становится видно глазом, а не в уме;
  • разложить дельту между двумя числами — «выручка выросла на 12 %» и четыре причины этого роста читаются как одна история;
  • прибавления и убавления вперемешку — цвет идёт по знаку, и направление каждого шага видно до чтения подписей;
  • шагов немного — до полутора-двух десятков; дальше подписи оси налезают друг на друга, и мост стоит свернуть до крупных статей.

Когда взять другое

НужноБерите
Сравнить величины по категориям, без преемственностиGrChartBar
Показать состав одного целого на один моментGrChartPie
Показать ход величины во времениGrChartLine
Показать, где теряются пользователи между ступенямиGrChartFunnel
Показать одно число с динамикойGrStatistic

Шаг `total` объявляет накопление, а не прибавляется к нему

kind: 'delta' (по умолчанию) — изменение от текущего накопления, kind: 'total' — абсолютное значение: столбец рисуется от нуля, а накопление сбрасывается на него. Это и позволяет поставить «На начало» и «На конец» реальными числами с бэкенда: если мост не сходится, последний столбец не совпадёт с вершиной предпоследнего, и ошибку в данных будет видно.

Соединитель к такому шагу не рисуется. Он не продолжает накопление, а объявляет его, и линия «отсюда сюда» соврала бы о преемственности.

Цвет идёт по знаку, а не по индексу серии

Мост — один ряд, и палитра серий здесь ничего не различает: различать надо прибавление (--gr-success) и убавление (--gr-danger). Итог и объявленное накопление красятся нейтрально (--gr-chart-1) — это не движение. Явный color шага сильнее любого из этих правил.

Нулевой шаг рисуется чертой

«Движения не было» — это факт, а не отсутствие данных. Столбец нулевой высоты пропал бы с рисунка, и читатель увидел бы историю, в которой такого шага нет вовсе. Вместо этого на уровне накопления встаёт черта толщиной --gr-chart-waterfall-zero-step.

Таблица несёт накопление, а не одну дельту

Скрытая таблица даёт три числа на шаг: изменение, накопление до и накопление после. По одной дельте мост не восстановить — высоту столбца задаёт именно накопление, и читающий без зрения обязан видеть то же, что зрячий видит по положению полосы.

Категория шага — его индекс, а не подпись

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

Границы

Мост не считает, из чего состоят его шаги, — их даёт потребитель. Мелкие шаги в «Прочее» он тоже не группирует: только вызывающий знает, что считать мелким. Вложенных (двухуровневых) мостов нет.

Установка

npm i @feugene/granularity-charts

Импорт

import { GrChartWaterfall } from '@feugene/granularity-charts/components/GrChartWaterfall'

API

API этого компонента ещё не посчитан: генератор витрины пока обходит только ядро. Пока его нет, справочник — в документации пакета.

Примеры 2

Basic

Basic
<script setup lang="ts">
/**
 * Мост отвечает на вопрос, которого нет у расходящихся столбцов: как из начала
 * месяца получился конец.
 *
 * Шаги `total` ставят реальные остатки с бэкенда, и если сумма движений с ними
 * не сходится, это видно глазом — последний столбец не совпадёт с вершиной
 * предпоследнего.
 */
const steps = [
  { label: 'На начало', value: 1240, kind: 'total' as const },
  { label: 'Новые', value: 318 },
  { label: 'Реактивации', value: 46 },
  { label: 'Заморозки', value: 0 },
  { label: 'Отток', value: -172 },
  { label: 'На конец', value: 1432, kind: 'total' as const },
]
</script>

<template>
  <div class="grid gap-3">
    <span class="text-[length:var(--gr-control-text-sm)] text-[var(--gr-muted-fg)]">
      Движение подписок за октябрь
    </span>

    <GrChartWaterfall
      :steps="steps"
      :height="280"
      aria-label="Движение подписок за октябрь"
    />

    <p class="text-[length:var(--gr-control-text-sm)] text-[var(--gr-muted-fg)]">
      Цвет идёт <strong>по знаку шага</strong>, а не по индексу серии: мост это один ряд, и различать
      в нём надо прибавление и убавление. «Заморозки» с нулём рисуются чертой — «движения не было»
      это факт, и пропадать он не должен.
    </p>
  </div>
</template>

Horizontal

Horizontal
<script setup lang="ts">
import { ref } from 'vue'

/**
 * Горизонталь берут, когда подписи шагов длиннее, чем позволяет ширина
 * категории: под вертикальной осью они налезли бы друг на друга.
 *
 * Оси в этом режиме рисует сам компонент — ось значений рамы вертикальна по
 * построению, а здесь она внизу.
 */
const steps = [
  { label: 'Обязательство на начало', value: 84_200, kind: 'total' as const },
  { label: 'Начислено по подпискам', value: 31_400 },
  { label: 'Куплено пакетами', value: 12_800 },
  { label: 'Списано', value: -28_900 },
  { label: 'Сгорело', value: -6100 },
]

const orientation = ref<'vertical' | 'horizontal'>('horizontal')
</script>

<template>
  <div class="grid gap-3">
    <div class="flex flex-wrap items-baseline justify-between gap-4">
      <span class="text-[length:var(--gr-control-text-sm)] text-[var(--gr-muted-fg)]">
        Экономика кредитов
      </span>

      <GrSegmented
        v-model="orientation"
        size="sm"
        :options="[
          { value: 'horizontal', label: 'Горизонтально' },
          { value: 'vertical', label: 'Вертикально' },
        ]"
        aria-label="Раскладка моста"
      />
    </div>

    <GrChartWaterfall
      :steps="steps"
      :orientation="orientation"
      :height="300"
      show-total
      aria-label="Экономика кредитов за период"
    />

    <p class="text-[length:var(--gr-control-text-sm)] text-[var(--gr-muted-fg)]">
      <code>showTotal</code> дорисовывает итоговый столбец от нуля. Накопления он не меняет — только
      показывает: соединитель к нему не ведёт, потому что он не продолжает мост, а объявляет его результат.
    </p>
  </div>
</template>

Доступность

Паттерн APG
При orientation: 'horizontal' шаги идут сверху вниз, и по ним ходят ↓/↑
Клавиши
шаг

Полный клавиатурный контракт пакета

Документация компонентаВсе компоненты