Пару недель назад я занималась интересной задачей. У меня был график с несколькими линиями и эффектом наведения мышки. Нужно было придумать простой алгоритм размещения лейблов текущих значений так, чтобы они не перекрывали друг друга.
🔗 https://codepen.io/gnykka/pen/ExqJrKY
Я сделала обычный линейный график на D3, поместив поверх всего контейнеры для ховер-элементов (лейблов и точек на линиях) и прямоугольник, который ловит события мыши. Для лейблов я использую
foreignObject
– он наконец-то более-менее поддерживается в разных браузерах, включая Safari (главное – не забыть явно указать его размеры и добавлять элементы с префиксом xhtml
).После отрисовки лейблов я вызываю специальную функцию для их размещения. Если кратко, то я прохожу по всем лейблам и сдвигаю их, если они накладываются на предыдущие. Если в результате сдвигов они выходят за пределы графика, то корректирую их положение обратно.
Получился очень простой алгоритм. Он эффективно работает если линий немного, а высота графика достаточная и точно вмещает все лейблы.