Под капотом: Drag, Touch и каскад CSS
Создание изменяемой по размеру UI-панели сложнее, чем кажется. Вам приходится одновременно управлять макетами, событиями касания и правилами CSS.
Вот три технических урока, извлеченных из моего недавнего редизайна UI для визуального сравнения (visual-diff).
1. Перестаньте использовать ширину окна для макетов
Не используйте window.innerWidth, чтобы определить, является ли ваш макет вертикальным или горизонтальным. Если пользователь изменит размер окна, ваша логика сломается.
Вместо этого используйте фактическое состояние CSS. Используйте getComputedStyle, чтобы проверить flex-direction. Это позволяет считать реальное значение после применения всех медиа-запросов. Так вы гарантируете, что логика перетаскивания соответствует тому, что пользователь видит на самом деле.
2. Обрабатывайте события касания и мыши вместе
Чтобы перетаскивание работало как на десктопе, так и на мобильных устройствах, нужен унифицированный подход.
- Используйте опциональную цепочку (optional chaining) для извлечения координат. Это позволит одной функции обрабатывать как события мыши, так и события касания.
- Используйте
{ passive: false }дляtouchmove. Браузеры по умолчанию делают события касания пассивными (passive), чтобы облегчить прокрутку. Если не установить это значение вfalse, вы не сможете вызватьe.preventDefault(). Без этого вызова страница будет прокручиваться во время попытки перетаскивания. - Прикрепляйте слушатели
moveиendк документу. Если пользователь проведет пальцем слишком быстро, он может выйти за пределы разделителя. Привязка к документу гарантирует, что перетаскивание продолжится, даже если указатель сместится.
3. Не боритесь со своей системой видимости
Я столкнулся с багом специфичности CSS. У меня был один класс для скрытия панелей и другой для задания направления макета.
Проблема:
.view-panel { display: none; }.diff-layout { display: flex; }
Поскольку у них была одинаковая специфичность, победил тот класс, который шел последним в файле. Это приводило к тому, что панели оставались видимыми, даже когда должны были быть скрыты.
Решение:
Никогда не позволяйте вспомогательному классу макета устанавливать свойство display. Пусть это делает класс видимости.
Вместо:
.diff-layout { display: flex; flex-direction: column; }
Используйте:
.view-panel.diff-layout { flex-direction: column; }
Это повышает специфичность и гарантирует, что класс макета меняет только направление, а не видимость.
Источник: https://dev.to/bonzai2carn/under-the-hood-drag-touch-and-css-cascade-in-a-real-diff-ui-1b66
