Как запретить годы в тиках оси d3.scaleTime ()?

С D3 (v4, обновление до v5 также возможно), я рисую временной ряд для временного интервала. Данные имеют неизвестную продолжительность, обычно это количество секунд, и у нас есть отметка даты начала и отметка даты окончания.

То, что я сейчас делаю для создания оси x, выглядит следующим образом, где startTime и endTime - числовые метки времени, width и height - числа, а xAxisGroupSelection - выбор D3:

const xScale = d3.scaleTime()
  .domain([0, startTime - endTime)
  .range([0, width])

const xAxis = d3.axisBottom()
  .scale(this.xScale)

xAxisGroupSelection
  .attr('transform', `translate(0, ${height})`)
  .call(xAxis)

Что-то это делает очень хорошо, так это дает разумные форматы для чисел. Например, он стилизует секунды, как :01, и миллисекунды, как .500, и если я получу довольно длинный интервал, который длится минуты или часы, он справится с этим.

Проблема в том, что поскольку он считывает метку времени 0, он добавляет метку года 1970 в начало профиля. Это, конечно, правильный год для метки времени 0, но я не хочу, чтобы он отображал год любой для временного ряда в секундах. Есть ли способ, используя конфигурацию D3, я могу сохранить форматирование времени по умолчанию, но не добавлять отметки для года (или месяца, дня и т. д.)?

<g class = "axis-group x-axis" transform = "translate(0, -12)" fill = "none" font-size = "10" font-family = "sans-serif" text-anchor = "middle">
  <path class = "domain" stroke = "#000" d = "M0.5,2V0.5H0.5V2"></path>
  <g class = "tick" opacity = "1" transform = "translate(0.5,0)">
    <line stroke = "#000" y2 = "2"></line>
    <text fill = "#000" y = "5" dy = "0.71em">1970</text> <!-- <=== -->
  </g>
  <g class = "tick" opacity = "1" transform = "translate(0.5,0)">
    <line stroke = "#000" y2 = "2"></line>
    <text fill = "#000" y = "5" dy = "0.71em">.500</text>
  </g>
  <g class = "tick" opacity = "1" transform = "translate(0.5,0)">
    <line stroke = "#000" y2 = "2"></line>
    <text fill = "#000" y = "5" dy = "0.71em">:01</text>
  </g>
  <g class = "tick" opacity = "1" transform = "translate(0.5,0)">
    <line stroke = "#000" y2 = "2"></line>
    <text fill = "#000" y = "5" dy = "0.71em">.500</text>
  </g>

Очевидно, есть много окольных способов, которыми я мог бы удалить или изменить это, от использования правила первого потомка CSS, чтобы скрыть его, до ручного выбора его в D3 и изменения его значения, но я хотел бы знать, можно ли это сделать в чистый способ использования API масштабирования / оси / формата / времени D3.

Могу ли я указать генератору тиков оси D3 игнорировать единицы времени, превышающие минуты? Я прошел через документы для шкал времени D3, но ничего не нашел. Думаю, можно было бы использовать Time.range(), но документы не дают мне много подсказок о том, как.


Обновлять: Похоже, мне нужно создать настраиваемую функцию для передачи в .tickFormat(), похожую на этот пример, но дублирующую средство форматирования времени по умолчанию с точкой отсечения, добавленной в условную логику. Итак, следующий вопрос: где мне найти логику формата времени D3 по умолчанию ...

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
775
2

Ответы 2

Глядя на исходный код D3, кажется, что форматировщик умных отметок времени по умолчанию находится внутри частных функций внутри d3-scale/src/time.js. Похоже, что это полностью «бери или оставляй»: вы можете использовать его точно так же, как есть, или полностью заменить, передав пользовательскую функцию в .tickFormat().

Итак, вам нужно создать пользовательскую функцию, дублирующую нужную логику внутри экспорта d3-scale/src/time.jscalendar, и особенно вложенного function tickFormat(date).

В моем случае важной частью этого является форматирование метки времени 0 как особого случая, который возвращает 0, а не самое широкое возможное описание первой миллисекунды 1970 года. Итак, моя функция по существу:

xAxis.tickFormat((date) => {
  // If this describes 0 milliseconds from the Epoch, return '0'
  if (d3.timeFormat('%Q')(date) === '0') return '0'
  // Then copy and paste as many lines as needed from `d3-scale/src/time.js`
  // from the `function tickFormat` adding the definitions of the formatters
  // like `formatMillisecond` etc from the `calendar` scope
})

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

Помимо кода в исходном коде D3, здесь есть демонстрация условных форматов времени в D3: https://bl.ocks.org/wboykinm/34627426d84f3242e0e6ecb2339e9065

Вы можете использовать .tickFormat () на своей оси с такой функцией форматирования:

function multiFormat(date) {
return (d3.timeSecond(date) < date ? formatMillisecond
: d3.timeMinute(date) < date ? formatSecond
: d3.timeHour(date) < date ? formatMinute
: d3.timeDay(date) < date ? formatHour
: d3.timeMonth(date) < date ? (d3.timeWeek(date) < date ? formatDay : 
formatWeek)
: d3.timeYear(date) < date ? formatMonth
: formatYear)(date);
}

Замените "formatSomething" форматированием d3.timeFormat ("x"). Вы можете найти примеры здесь https://bl.ocks.org/zanarmstrong/raw/ca0adb7e426c12c06a95/.

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

%Y - for year boundaries, such as "2011".
%B - for month boundaries, such as "February".
%b %d - for week boundaries, such as "Feb 06".
%a %d - for day boundaries, such as "Mon 07".
%I %p - for hour boundaries, such as "01 AM".
%I:%M - for minute boundaries, such as "01:23".
:%S - for second boundaries, such as ":45".
.%L - milliseconds for all other times, such as ".012".

Другие вопросы по теме