Форматирование подписей делений через callback

Механизм подписей делений (ticks) в Chart.js основан на системе масштабов (scales), где каждое значение оси может быть преобразовано перед отображением. Ключевым инструментом кастомизации выступает функция callback, позволяющая перехватывать момент формирования текстового представления тиков и изменять его произвольным образом.

Структура настройки ticks

Каждая ось в Chart.js имеет блок конфигурации ticks, внутри которого и определяется поведение подписей:

options: {
  scales: {
    x: {
      ticks: {
        callback: function(value, index, ticks) {
          return value;
        }
      }
    }
  }
}

Параметры callback-функции:

  • value — исходное значение тика (число, строка или объект в зависимости от типа шкалы)
  • index — индекс текущего тика
  • ticks — массив всех тиков оси

Функция возвращает строку, которая будет отображена на графике.


Базовое форматирование чисел

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

ticks: {
  callback: function(value) {
    return value + " ₽";
  }
}

Более гибкий вариант с форматированием:

ticks: {
  callback: function(value) {
    return Number(value).toFixed(2);
  }
}

Использование Intl.NumberFormat обеспечивает локализованное отображение:

ticks: {
  callback: function(value) {
    return new Intl.NumberFormat('ru-RU').format(value);
  }
}

Добавление единиц измерения

При визуализации физических величин, метрик или статистики часто требуется явное указание единиц.

ticks: {
  callback: function(value) {
    return value + " км";
  }
}

Для более сложных случаев возможно условное форматирование:

ticks: {
  callback: function(value) {
    if (value >= 1000) {
      return (value / 1000) + " тыс. м";
    }
    return value + " м";
  }
}

Форматирование процентов

При работе с долями или коэффициентами применяется преобразование в проценты:

ticks: {
  callback: function(value) {
    return (value * 100) + "%";
  }
}

Для стабилизации вывода и устранения длинных дробей:

ticks: {
  callback: function(value) {
    return (value * 100).toFixed(1) + "%";
  }
}

Работа с датами на оси времени

Time-scale в Chart.js часто используется для временных рядов, где форматирование подписей критично для читаемости.

ticks: {
  callback: function(value) {
    const date = new Date(value);
    return date.toLocaleDateString('ru-RU');
  }
}

Форматирование с контролем точности:

ticks: {
  callback: function(value) {
    const date = new Date(value);
    return date.toLocaleString('ru-RU', {
      day: '2-digit',
      month: 'short'
    });
  }
}

Условное отображение подписей

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

ticks: {
  callback: function(value, index) {
    return index % 2 === 0 ? value : "";
  }
}

Другой подход — фильтрация по значению:

ticks: {
  callback: function(value) {
    return value > 0 ? value : "";
  }
}

Форматирование больших чисел

При работе с масштабами в миллионах и миллиардах используется сокращённая запись.

ticks: {
  callback: function(value) {
    if (value >= 1e9) {
      return (value / 1e9).toFixed(1) + " млрд";
    }
    if (value >= 1e6) {
      return (value / 1e6).toFixed(1) + " млн";
    }
    if (value >= 1e3) {
      return (value / 1e3).toFixed(1) + " тыс";
    }
    return value;
  }
}

Такой подход позволяет сохранить визуальную компактность оси при больших диапазонах значений.


Использование локализации и Intl API

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

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'currency',
  currency: 'RUB'
});

ticks: {
  callback: function(value) {
    return formatter.format(value);
  }
}

Для процентов:

const percentFormatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent',
  maximumFractionDigits: 1
});

ticks: {
  callback: function(value) {
    return percentFormatter.format(value);
  }
}

Форматирование в зависимости от масштаба данных

При динамических данных часто требуется адаптивное форматирование, зависящее от диапазона значений.

ticks: {
  callback: function(value, index, ticks) {
    const max = Math.max(...ticks.map(t => t.value || t));
    
    if (max > 1000000) {
      return (value / 1000000).toFixed(1) + "M";
    }
    
    if (max > 1000) {
      return (value / 1000).toFixed(1) + "K";
    }
    
    return value;
  }
}

Различия поведения в Chart.js v3 и v4

В актуальных версиях Chart.js механизм callback сохраняет совместимость, однако структура scales стала более строгой.

Особенности:

  • доступ к значениям тиков может зависеть от типа scale
  • в time-scale значение часто приходит в формате timestamp
  • рекомендуется избегать мутаций входных данных ticks

Пример корректного подхода:

ticks: {
  callback: (value) => {
    return String(value);
  }
}

Совмещение callback с другими параметрами ticks

Callback используется совместно с другими настройками:

ticks: {
  maxRotation: 0,
  autoSkip: true,
  callback: function(value) {
    return value + " ед.";
  }
}

Параметры:

  • maxRotation — угол поворота подписей
  • autoSkip — автоматическое скрытие части тиков
  • callback — финальное преобразование текста

Обработка сложных объектов данных

При кастомных scale или внешних адаптерах значение может приходить как объект.

ticks: {
  callback: function(value) {
    return value.label || value.y || value;
  }
}

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


Комбинирование форматирования с логикой отображения

Callback позволяет объединять форматирование и бизнес-логику отображения:

ticks: {
  callback: function(value, index) {
    if (index === 0) {
      return "Начало: " + value;
    }
    
    if (index === ticks.length - 1) {
      return "Конец: " + value;
    }
    
    return value;
  }
}

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


Ограничения callback-подхода

Использование callback требует учёта производительности при большом количестве тиков. Частые вычисления, особенно с форматированием дат или локализацией, могут влиять на скорость отрисовки.

Типичные оптимизации:

  • вынос форматтеров за пределы callback
  • кэширование результатов форматирования
  • минимизация вычислений внутри функции

Пример с кэшированием:

const cache = new Map();

ticks: {
  callback: function(value) {
    if (cache.has(value)) {
      return cache.get(value);
    }
    
    const formatted = value + " шт";
    cache.set(value, formatted);
    return formatted;
  }
}