michael_mashush
@michael_mashush

Как правильно позиционировать тултип?

Решил попробовать сделать свой компонент Tooltip и столкнулся со следующей проблемой - не могу продумать алгоритм позиционирования тултипа. На данный момент его можно позиционировать в 12 позициях (как в Material UI): top/right/bottom/left + для каждой стороны есть start/center/end.

Чтобы проверить нужно ли мне пересчитывать позицию я использую метод getBoundingClientRect, который проверяет выходит ли тултип за пределы окна. Можно, конечно, перебрать через if все возможные варианты, но вдруг здесь предложат идеи получше.

Например, если тултип достаточно широкий и привязан к кнопке в левой части шапки сайта (например, бургер-меню), то слева он будет немного вылезать за край окна, поэтому его нужно прижать слева (задать позицию bottom-start), чтобы он расширялся вправо:

66195c79d4191406081116.jpeg
66195c839e831986569367.jpeg

Повторюсь - вопрос в том, как реализовать это с точки зрения алгоритма, а не как конкретно это сделать на реакт, как изменять состояние и все такое - это уже реализовано, важна логика, по которой тултип будет изменяться)
  • Вопрос задан
  • 85 просмотров
Решения вопроса 2
rqdkmndh
@rqdkmndh
Web-разработчик
Ключ к эффективному алгоритму здесь – определить, достаточно ли места по каждой из четырех сторон (сверху, снизу, слева, справа) от активатора, чтобы тултип вместился без выхода за пределы экрана.

Вот базовая идея алгоритма:

1. Определить размеры и положение элемента-активатора, используя getBoundingClientRect.
2. Определить размер окна браузера.
3. Рассчитать доступное пространство в каждом из направлений: сверху, снизу, слева, и справа от элемента.
4. Используя размеры тултипа, определить может ли он поместиться в каждом из этих направлений.
5. Если тултип не помещается в первоначальном направлении:
- Испытать альтернативные позиции на основе доступного пространства и размеров тултипа.
- Выбрать позицию, которая наилучшим образом подходит и не заходит за пределы экрана.
В реальной реализации вам нужно будет также учесть размеры самого тултипа, чтобы точно определить, поместится ли он в доступном пространстве, и возможно, предусмотреть отступы от краев экрана.

Также важно обеспечить динамическую перепроверку позиции тултипа при событиях, которые могут изменить положение или размер активатора, например, при изменении размера окна браузера (event resize) или прокрутке страницы (event scroll).

И наконец, поскольку это может быть ресурсоемкий процесс, обдумайте использование debounce функции для событий, вызываемых слишком часто.
Ответ написан
VoidVolker
@VoidVolker Куратор тега JavaScript
Dark side eye. А у нас печеньки! А у вас?
Примерно вот так:
Парковка элементов относительно друг друга через точки

    Point: 1|2|3|4
       topLeft     topRight
              1___2
              |   |
              |___|
              4   3
    bottomLeft     bottomRight

    Edges        1
               _____
              |     |
           4  |     |  2
              |_____|

                 3

    Point format:
      [targetPoint, itemPoint]

    Docking variants:
                [1,3]      [2,4]
                  __        __
    item   ->    |_3|______|4_|
    target ->       |1    2|
                  __|4____3|__
                 |_2|      |1_|

                [4,2]      [3,1]

        __
       |4_|___ __
     __|1    2|1_|
    |_3|4____3|
           |_2|

            __
     __ ___|_3|
    |_2|1    2|__
       |4____3|4_|
       |1_|

       1_________2
       |1_|   |_2|
       |__     __|
       |4_|___|_3|
       4         3


Я уже реализовывал кучу лет назад данный алгоритм для парковки элементов относительно друг друга с учетом всех важных факторов. И реализация на шарпе получилась объемом в 800 сотен строчек кода с комментариями, при этом сам алгоритм выбора точки - монстр в более чем 300 строчек кода и сплошной набор из пачки ифов глубиной до 6 и до 12 штук подряд, а так же набором свитчей тоже в количестве шести штук и глубиной до двух (местами внутри ифов). И это еще с учетом сокращений за счет некоторых дополнительных математических и логических вычислений. (Откопал еще и JS версию).
Если кому интересно - пишите, могу поделиться кодом.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы