Проектирование интерфейсов с Drag and Drop
Что такое Drag and Drop и когда его использовать Drag and Drop (drag-and-drop) (с англ. «потащи и брось») — это способ взаимодействия с элементами (объектами) интерфейса при помощи мыши, тачпада или сенсорного экрана путём последовательного выполнения на этих элементах трёх операций: «захвата» (drag), перемещения и «отпускания» (drop) на другую позицию или поверх другого элемента интерфейса. Далее в статье я буду периодически использовать термин «перетаскивание» для обозначения действия, которое объединяет эти три операции.
Перетаскивание отлично подходит для определённых сценариев, так как позволяет сократить количество действий над элементами и упростить взаимодействие с интерфейсом. Всего можно выделить два класса сценариев, в которых используется Drag and Drop:
Когда необходимо переместить элемент на новую позицию;
Например, переместить файл в папку на рабочем столе операционной системы можно всего лишь одним действием перетаскивания, вместо того, чтобы последовательно выполнять команды: выделить файл → вырезать файл → открыть папку → вставить файл → закрыть папку.
Когда необходимо изменить размеры/форму элемента.
Пример для этого сценария — это изменение размеров окна запущенной программы. Это действие можно выполнить и без перетаскивания, в частности, используя клавиатуру, особенно если разработчики интерфейса позаботились о доступности (accessibility) интерфейса. Однако, с помощью Drag and Drop это можно сделать намного проще и быстрее.
На первый взгляд, Drag and Drop может показаться простым в использовании, а, следовательно, в проектировании и разработке, ведь этот подход основан на опыте взаимодействия с реальными физическими объектами: нужно просто «схватить» и перетащить объект на другое место. Вот только в реальном мире мы чаще всего можем безошибочно определить, можно ли переместить тот или иной объект, какое новое место он может занять, и что может повлечь за собой такое перемещение. При проектировании и разработке цифровых интерфейсов недостаточно просто скопировать механику захвата, переноса и отпускания физических объектов. Нужно сопроводить эту механику множеством дополнительных графических нюансов, которые позволят пользователю получать обратную связь на каждом этапе взаимодействия с объектами, чтобы это взаимодействие казалось логичным и удобным.
В процессе проектирования интерфейсов с Drag and Drop, необходимо ответить на некоторые важные вопросы:
Нужна ли пользователям в конкретном рассматриваемом случае функция Drag and Drop?
Как пользователи узнают, что именно можно переместить?
Как пользователи узнают, где находится зона сброса объекта?
Как узнать, куда можно переместить объект, а куда перемещать запрещено?
Как различать, что пользователь не просто кликнул по объекту, а перемещает его?
Какие устройства могут быть задействованы пользователем при перетаскивании?
Необходимо ли добавить альтернативные способы взаимодействия с интерфейсом в целях повышения доступности?
В этой статье я хочу дать ответы на эти вопросы, и начну с описания визуальных компонентов, которые участвуют в процессе перетаскивания. Давайте рассмотрим их более детально, а также обсудим, какие нюансы их поведения и внешнего вида нужно учитывать при проектировании перетаскивания.
Какие компоненты участвуют в перетаскивании Перетаскиваемый элемент (объект) Перетаскиваемый элемент может быть любым видимым объектом на экране, который можно перетаскивать с помощью движения курсора или пальца на сенсорном дисплее. Иногда элемент доступен для захвата полностью, а в некоторых случаях только его отдельная область — так называемая «ручка для захвата».
Ручка для захвата Ручка для захвата — это специальная зона элемента, которая предназначена только для его захвата и перетаскивания. Обычно эта зона помечена иконкой, однако, для этой иконки не существует одной общеупотребительной графической метафоры, как для иконки закрытия окна (крестик) или кнопки «сохранить» (изображение дискеты). Впрочем, за многие годы практики дизайнеров интерфейсов сложились варианты возможных иконок, которые можно использовать для обозначения зоны для захвата.
Главное правило при выборе иконок — соблюдать принцип консистентности и использовать один вариант иконок на всём проекте.
Индикатор перетаскиваемого элемента В процессе перетаскивания может переноситься не сам элемент, а соответствующий ему объект, который будет обозначать исходный элемент. Например, при перетаскивании в почтовом клиенте нескольких писем из входящих сообщений внутрь отдельной папки, по экрану могут перемещаться не сами элементы списка писем, а индикатор, который занимает меньше места, при этом отображает всю необходимую информацию о перетаскиваемых элементах.
Изначальная позиция перетаскиваемого элемента Если для конкретной задачи важно сохранять знание о том, где находился элемент до того, как его начали перетаскивать, этот элемент может дублироваться в его изначальной позиции до момента сброса. В этом случае важно показать, что в изначальной позиции находится не сам элемент, а его копия, которая пропадёт, когда элементу найдётся новое место. Лучше всего передать это состояние через добавление прозрачности копии элемента.
Однако, часто можно встретить варианты реализации Drag and Drop, в которых элемент сразу же пропадает из изначальной позиции, а на его месте появляется пустое отверстие. Это отверстие может сразу заполниться другими элементами, если при перетаскивании меняется порядок элементов в одном или двух измерениях.
Контейнер, содержащий элемент Контейнер — это контекст, в котором существует элемент. В некоторых сценариях Drag and Drop позволяет переместить элемент из одного контейнера в другой, а, следовательно, сменить контекст для элемента. Если элементы выстроены в список или грид, то после перетаскивания этих элементов из контейнера или внутрь него, другие элементы должны будут поменять своё положение в контейнере, а сам контейнер должен перестроиться в зависимости от нового наполнения.
Цель перетаскивания (зона сброса) Целями перетаскивания элемента могут быть разные объекты в интерфейсе: новое место внутри исходного или другого контейнера, новая позиция в связной структуре объектов, а также любой объект, после сброса элемента на который будет инициировано то или иное действие.
Подсказки на зоне сброса Зона сброса может дополнительно выделяться и подсвечиваться при приближении к ней элемента, при пересечении элементом её границ, а также менять своё состояние и внешний вид в момент сброса и в процессе дальнейшего выполнения действий, завязанных на событие сброса. Например, зона сброса может отображать прогресс загрузки сброшенных на неё файлов.
В случаях, когда перемещение элементов приводит к изменению их порядка в списке или гриде или к перестроению связей с другими элементами в структуре, используется элемент-индикатор, отображающий позицию, в которой окажется элемент при сбросе. Такой случай мы разберём чуть ниже, когда будем детально разбирать события, из которых состоит процесс перетаскивания элементов.
Курсор Для работы с перетаскиваемыми элементами предусмотрены специальные состояния курсоров, которые отличаются для пользователей MacOS и Windows. Для MacOS необходимо использовать открытый курсор в состоянии grab при наведении на перетаскиваемый элемент, а при самом действии перетаскивания менять на закрытый курсор в состоянии grabbing. Для Windows принято использовать курсор в состоянии move для обоих действий. При пересечении перетаскиваемого элемента с теми зонами, где он не может быть сброшен, следует менять курсор на состояние no-drop.
Для операции изменения размеров (ресайза) необходимо использовать состояния курсоров с префиксом rezise — в зависимости от стороны, в которую будет тянуться курсор для ресайза.
Для каких сценариев можно использовать Drag and Drop Далее предлагаю детально рассмотреть конкретные сценарии использования Drag and Drop и примеры, в которых можно увидеть реализацию этих сценариев. Предложенная здесь классификация покрывает большинство возможных сценариев использования функции перетаскивания.
Если ваша задача относится к одному из этих сценариев, то, вполне возможно, целесообразно предусмотреть функцию Drag and Drop для её решения.
Перемещение элемента внутри контейнера Этот сценарий можно считать базовым случаем перемещения элемента, так как при этом не происходит смена контекста, в котором существует элемент. Примером такого сценария может быть изменение положения элемента интерфейса на холсте — при этом меняются только координаты элемента на плоскости холста. Элемент может перемещаться свободно или же быть привязанным к сетке холста и при перемещении менять завязанные на сетку координаты. При перемещении элемента на холсте могут появляться подсказки, по которым можно соориентировать новую позицию элемента относительно позиций других объектов.
Конкретные примеры для этого сценария — профессиональные инструменты, такие как онлайн-инструмент для прототипирования интерфейсов Figma, коллаборативная визуальная платформа Miro и графический редактор Canva. В этих системах перемещение объектов ограничено пределами холста, а если холст бесконечный, то перемещение не ограничено вовсе.
Перемещение элемента между контейнерами В данном сценарии элемент при перемещении исчезает из изначального контейнера и появляется в новом. Таким образом, областью сброса для перетаскиваемого элемента становится новый контейнер.
Примером такого сценария может быть канбан-доска Trello, в которой задачам задаётся новый статус путём переноса их из одной колонки в другую.
Перемещение элемента с удалением В этом сценарии элементы можно перемещать только на определённые объекты на странице, а по завершении перемещения перетаскиваемые элементы будут удалены из исходного контейнера.
Классические примеры такого сценария — перемещение писем в отдельную папку в почтовом клиенте типа Gmail или сброс файлов в корзину для их последующего удаления.
Изменение порядка элементов в одном измерении В этом сценарии перемещение элемента происходит внутри одного контейнера и доступно только в пределах одного измерения: вверх-вниз или влево-вправо.
Классическим примером такого сценария является сортировка списка — вертикального или горизонтального. При этом список может быть как плоским, так и иерархическим, то есть у каждого элемента списка могут быть дочерние элементы, и эта связь должна быть чётко отражена в дизайне списка как для его статичного состояния, так и для состояния, в котором эти связи меняются вследствие перетаскивания элементов.
Изменение порядка элементов в двух измерениях Данный сценарий похож на предыдущий, но осуществляется сразу в двух измерениях.
Примером такого сценария может быть визуальное построение интерфейса из готовых виджетов, выстроенных по заранее заданной или свободной сетке (гриду).
Изменение отношений между элементами В этом сценарии жёстко ограничено то, куда можно переместить элемент, так как его позиция должна быть встроена в некую структуру отношений между всеми элементами. При перемещении элементов перестраиваются связи между ними внутри этой структуры.
Примером такого сценария может быть перестроение объектов и связей между объектами в интеллектуальной карте (mind mapping tools).
Инициация действия на сброс объекта Если в предыдущих сценариях объекты перетаскивались в первую очередь для изменения их положения в пространстве или для перестроения связей в структуре, то при этом сценарии перетаскивание всегда вызывает какое-то действие.
Примерами здесь могут быть взаимодействия с файловой системой или действия, имитирующие такие взаимодействия. Например, так можно запускать файлы, отпустив иконку файла над иконкой конкретного приложения в операционной системе, или загружать файлы из операционной системы на сервер сайта путём сброса их в специальную зону сброса в веб-интерфейсе.
Изменение размера контейнера Этот сценарий задействуется, когда необходимо изменить размеры контейнера для повышения читаемости интерфейса или для более удобного взаимодействия с содержимым контейнера.
Примером такого сценария может быть изменение ширины колонки или строки внутри таблицы, например, для повышения удобства чтения и редактирования их содержимого.
Геометрические действия с объектами Данный сценарий взаимодействия чаще всего используется для работы не с функциональными элементами интерфейса, а с некими графическими объектами.
Примеры этого можно увидеть в графических редакторах, таких как Photoshop, Illustrator или Figma при изменении геометрических размеров или формы тех или иных графических объектов.
Составные действия В эти сценарии входят комбинации действий, которые производятся в пределах одной операции перетаскивания объектов.
Это может быть изменение положения маркера на карте (это пример свободного перемещения объекта в пределах одного контейнера) и последующий запуск действия по построению маршрута с позицией этого маркера в момент отпускания маркера в новом положении.
Какие события сопровождают Drag and Drop Мы рассмотрели сценарии, в которых может быть целесообразно использование Drag and Drop. В этом разделе я хочу описать события, которые сопровождают процесс перетаскивания применительно к этим сценариям.
Наведение курсора на перетаскиваемый элемент Если навести курсор на перетаскиваемый элемент, он должен выделяться особым образом, как бы приглашая пользователя к действию. Это может быть рамка вокруг элемента, изменённый фон или появление иконки, указывающей на то, что элемент можно перетаскивать. Сам курсор должен измениться со стандартного состояния на состояние grab или move, в зависимости от операционной системы пользователя.
Нажатие клавиши мыши на перетаскиваемом элементе Это событие примечательно тем, что его стоит отличать от обычного клика по элементу. Например, в приложении Trello весь элемент карточки задачи доступен как для перетаскивания, так и для обычного клика. При коротком клике на карточку задачи открывается модальное окно для редактирования содержимого карточки, а при длинном — запускается событие перетаскивания. Важно правильно подобрать длительность нажатия, которое вызывает перетаскивание таким образом, чтобы событие перетаскивания запускалось не слишком поздно, но и не слишком рано.
Другая проблема, которая иногда может мешать выполнить клик на элементе — это так называемые небрежные нажатия (sloppy clicks). Иногда рука при клике на кнопку мыши или на поверхность тачпада может совершить небольшое лишнее движение. Это движение может заставить курсор сдвинуться на несколько пикселей. Таким образом, сразу же сработает событие перетаскивания, хотя ожидался обычный клик. Эту проблему можно решить введением порога дистанции, после прохождения курсором которой будет инициировано событие перетаскивания.
В некоторых библиотеках для работы с Drag and Drop такие ограничения по длительности и дистанции предусмотрены изначально, и обычно находятся в пределах от 50 до 500 мс для длительности нажатия, и от 3px до 5px для порога дистанции. При разработке стоит поэкспериментировать с данными значениями, чтобы добиться наиболее комфортного для пользователя поведения.
Если работа происходит в MacOS, то при нажатии на объект или на специальную зону внутри него, предназначенную для перетаскивания, курсор должен измениться с состояния grab на состояние grabbing.
В заключение В этой статье мы рассмотрели большое количество нюансов, касающихся интерфейсов с использованием подхода Drag and Drop.
Сначала мы познакомились с определением этого подхода и списком вопросов, на которые важно ответить при проектировании взаимодействия с такими интерфейсами. Далее мы рассмотрели компоненты, которые участвуют в процессе перетаскивания и увидели ключевые особенности, связанные с ними. Ответ на вопрос о целесообразности добавления функции перетаскивания мы рассмотрели через разбор сценариев, в которых может использоваться Drag and Drop, увидели конкретные примеры реализации этих сценариев. После этого мы последовательно и детально разобрали все события, которые сопровождают процесс перетаскивания от наведения на перетаскиваемый элемент до отмены всего перетаскивания. Далее мы остановились на особенностях Drag and Drop в мобильных интерфейсах с использованием сенсорных экранов. В последней части мы рассмотрели спорные ситуации, в которых Drag and Drop или не подходит совсем, или же требует дополнения альтернативными подходами для решения той или иной задачи, а также познакомились с этими альтернативами.
Drag and Drop — это технология управления элементами интерфейсов, которая подходит далеко не для каждой задачи, при этом встречается практически ежедневно в большом количестве приложений — как в настольных, так и в мобильных, как в нативных, так и в веб-приложениях. Знание всех особенностей этой технологии позволит проектировать и разрабатывать наиболее удобные и комфортные в использовании интерфейсы.