Я хочу динамически разрешать метки на гистограммах в зависимости от ширины столбцов - если они становятся тонкими, метки выглядят не очень хорошо и часто перекрываются. Однако на самом деле я не хочу возиться с некоторыми низкоуровневыми манипуляциями с элементами SVG, и Nivo нужно что-то использовать для расчета ширины полос; Я мог бы использовать то же самое, чтобы определить, подойдут ли этикетки. Я жду чего-то напрямую от д3, но не знаю.





Итак, я просмотрел исходный код Nivo и после некоторых поисков нашел то, что искал (вроде как) здесь:
const bandwidth = (indexScale.bandwidth() - innerPadding * (keys.length - 1)) / keys.length
Это версия сгруппированной гистограммы (в отличие от составной, но в этом случае это просто = indexScale.bandwidth()), где innerPadding — это отступы между столбцами в группе, а keys — это клавиши, используемые для одной группы. Однако indexScale — это внутренний объект, созданный с помощью (я упрощаю) createBandScale, который вы можете увидеть здесь:
export const createBandScale = <Input extends StringValue>(
{ round = true }: ScaleBandSpec,
data: ComputedSerieAxis<Input>,
size: number,
axis: ScaleAxis
) => {
const scale = scaleBand<Input>()
.range(axis === 'x' ? [0, size] : [size, 0])
.domain(data.all)
.round(round)
return castBandScale<Input>(scale)
}
Эта функция доступна через @nivo/scales, поэтому я могу использовать ее в своих целях. Однако после некоторого тестирования я обнаружил, что мои результаты были неверными: кажется, что в вычислениях игнорируются отступы между группами, поэтому рассчитываемая мной ширина была больше фактической ширины полосы; Я не знаю, почему это так, возможно, это рассматривается где-то дальше, но для моих целей мне просто нужно было создать BandScale вот так:
const bandScale = createBandScale(
{ round: false },
{ all: xAxis },
totalWidth,
"x"
).paddingInner(padding) // << this is the important part
Единственной оставшейся проблемой было определение общей ширины элемента SVG, и, к счастью, в кодовой базе Nivo есть такой крючок, но он не является частью пакета, поэтому я добавил его в свой собственный код - вот крюк.