构建响应式拖放 UI



拖放,在 Web 应用程序的上下文中,为人们提供了一种视觉方式来拾取和移动元素,就像我们在现实世界中一样。这种拟物化使具有拖放交互的 UI 易于使用。

拟态是软件中的对象模仿其现实世界对应物的地方。–以色列国防军

虽然在交互式看板列表中拖动数字卡片可能没有明显的现实世界对应物,例如 Trello,但该动作本身对人类来说是熟悉的,因此很容易学习。

Trello 拖放
现代拟物化是数字和工业设计交汇处的桥梁。它是关于在不牺牲可用性的情况下促进非传统设备交互。它是关于在我们人类生理学的背景下丰富和活跃现实世界的物体。贾斯汀·贝克

尽管这些交互成为网络上各种工具的共同特征——从 Trello 之类的看板到 Gmail 之类的实际电子邮件收件箱,但它们实际上很难构建。我在自己制作时发现了这一点,即使使用开源库也是如此。这是它目前的样子:

在信中拖放

在本文中,我将介绍:

  • 设计考虑:可访问性等
  • React 库:构建拖放 UI 的几个选项
  • 使其响应:在移动设备上拖放

1.拖放设计

在研究不同的库和实现拖放的技术方面之前,我建议从设计考虑开始。什么是好的拖放功能?这里有几件事:

无障碍

对于拖放而言,可访问性可能具有挑战性,传统的拖放库会跳过它:

传统上,拖放交互仅是鼠标或触摸交互。亚历克斯·里尔登

如果用户不能使用他们的交互方法进行物理拖放,你如何让它变得更容易?键盘交互是一个不错的选择,例如:

  • 按空格键拿起
  • 使用箭头键移动选定的元素
  • 再次使用空间下降

如果没有先验知识,这个领域听起来可能很难实施。一个开始探索的好地方是ARIA Live Regions,它可以帮助您在拖放交互期间传达操作、身份和状态。Jesse Hausler(Salesforce 的首席可访问性专家)介绍了他的文章“可访问拖放的 4 种主要模式”。

拖动手柄

拖动手柄是您单击或触摸以拾取和移动项目的可拖动元素的区域。它也可以称为可拖动区域:

Letter中的小拖动手柄

上面的示例显示了小手柄,它可以用于桌面设备上带有鼠标光标的人,但对于小触摸屏上的胖手指可能会很棘手。在这种情况下,您可能需要进行一些更改。

您也可以完全使用拖动手柄进行提问。虽然在某些情况下很有帮助,但在其他情况下,实际上可能没有必要:

对于通常不涉及拖放的组件,拖动句柄可帮助用户发现拖放作为可用操作。但在拖放始终是预期行为的情况下,就没有必要了。Grace Noh,在漫威博客上

概念示例

这在 Notion 中很明显。对于他们的常规列表视图,存在一个非常小的拖动手柄,但对于看板视图却没有。在那种情况下,整张卡片变成了可拖动的表面:

拖动手柄(左),看板中没有拖动手柄(右)

拖放状态

您的用户如何知道拖动何时开始?状态的使用可能是一个很好的指标。一些需要考虑的状态是:

  • 悬停时
  • 按下(或单击)
  • 拖动时
  • 掉落时
按下时(左),拖动时(右)

这些听起来很明显,但这也取决于输入设备。例如,触摸设备上并没有真正的悬停状态。

将这些正确地用于您的应用程序非常重要,Grace Noh 在她的文章Drag and Drop for Design Systems中对此进行了更深入的探讨。在其中,她介绍了系统光标、状态样式、可供性等:

设计系统的拖放

幸运的是,像Alex Reordon这样的人在构建我们都可以使用的开源拖放库时也考虑了上述很多因素。查看他的帖子,重新思考拖放,了解更多信息。在下一节中,我将向您展示我是如何发现使用 Alex 的React Beautiful DnD的,以及为什么我最终没有使用它:

2.拖放库

有了现成的拖放库,您可能希望避免从头开始创建自己的拖放库。但是,重要的是要注意开放源代码库存在一些限制,导致它们不适用于您的设计。在这种情况下,从头开始实际上可能比尝试构建解决方法更快。

例如,Marvel 设计工具有一个独特的用例,组件可以在“ Sections ”之间垂直拖动,也可以水平拖动:

Marvel 部分之间的垂直拖动
Marvel Sections中的水平拖动

像这样的 UI 中的特定需求可能使其成为重新考虑拖放的更好选择。我自己发现了这一点,如下所示。

现在您知道存在限制,我将浏览我尝试过的库。这些只是 React 库,因为 Letter 是用 React 制作的:

反应美丽的 DnD

这是使用最广泛的库之一,查看这些 GitHub 统计信息:

好处

这个库的好处是巨大的——它涵盖了上一节中概述的各种设计场景。在我看来,它的可访问性支持特别使它与众不同:

  • 全键盘支持 (重新排序、组合、在列表之间移动)
  • 键盘多拖支持
  • 键盘 自动滚动
  • 出色的 屏幕阅读器支持

在输入设备支持方面也是无限的。看,一个思想传感器🤯:

思想传感器
用大脑拖放 🧠,作者:Charlie Gerard

…或者网络摄像头传感器呢:

网络摄像头传感器
网络摄像头传感器拖放,作者Kang-Wei Chan

请参阅这些示例,以及更多此处。

缺点

我认为它拥有一切,但有几个限制意味着我不能使用这个库:

  • 您不能有嵌套容器,这意味着 2 个拖放列不能重叠。这使我的弹出菜单无法与库一起使用。
  • 拖动期间没有占位符(请参阅下一节)

如果这些缺点不影响您,请在此处尝试。并且有一个完整的视频指南将引导您逐步实现它:

我希望在嵌套滚动容器问题得到修复后切换回 React-Beautiful——他们目前正在解决这个问题。

反应平滑 DnD

不如 React-Beautiful 酷,但这是我目前使用的。这个是Kutlu Sahin的,它有很大的优势:

好处

  • 可定制的放置占位符——见上面的蓝色虚线。这对整体体验来说是一个很大的改进,因为毫无疑问该组件将落在哪里。
  • 拖拽速度较慢——React-beautiful-dnd 几乎太敏感了,这使得在我的实现中将组件放置在正确的位置变得很棘手。这个库感觉更受控制且更慢,这对于大型组件效果更好。
  • 对重叠容器没有限制——这解决了我在使用 React-beautiful-dnd 时遇到的问题

缺点

没有提到 React-Smooth-DnD 的键盘支持或可访问性注意事项。现在众所周知,我们应该首先构建可访问性,我在前面的部分中对此进行了概述。虽然在理论上它很容易和显而易见,但使用非常有限的时间和资源的现实意味着使拖放功能易于访问是很难单独处理的。为此,我必须依赖开源库。

我尝试的另一个是React-DnD。这是我用过的第一个,当时 Letter 应用程序被称为 Email Otter。添加动画时我发现它很难使用,所以切换到 React-beautiful-dnd:

https://www.youtube.com/watch?time_continue=25&v=eYYQKeS0PoU&feature=emb_logo

库可以互换

总的来说,可以说我经历了拖放地狱,然后又回来了。到目前为止,我还在这篇文章中输入了 30 次“拖放”🤷🏽‍♂️。

救世主的一件事是所有这些拖放 (31) 库的工作方式相对相似,因此它们之间的互换并非不可能。React-beautiful-dnd 和 React-smooth-dnd 都基于相似的概念——拖拽容器和可放置项,使得 React 组件类似于从高层次实现。

事后看来,在将它们烘焙到您的应用程序之前,绝对值得在CodeSandbox中使用它们。快速搜索可以为您提供React-beautiful-dnd、React-smooth-dnd和其他任何东西的可编辑演示。调查您使用的任何库所需的数据结构,并确保您的应用程序结构可以灵活切换。

使其响应

您永远不知道有人在尝试您的应用程序时会使用什么尺寸的屏幕或设备类型。如果他们使用移动设备,则需要考虑更多事项:

  • 拖动手柄大小:在触摸设备上,是否应该有拖动手柄?拖动手柄可以用吗?
  • 触摸输入:触摸不同于鼠标点击。有不同的事件和状态,例如触摸与悬停。
  • 拖动表面:也许整个组件应该是一个可拖动的表面。如果是这样,是否应该有一个按钮来激活拖动模式?当组件被触摸拖动时,我们需要确保文本不会被错误地突出显示。

在上述 3 个方面,我发现触摸输入是更具挑战性的方面之一。当用户触摸可拖动组件,然后滑动移动它时,整个页面会随之滚动。因此,必须在拖动组件期间禁用原生触摸滚动。为此,React 有一个合成事件列表供我们利用(双关语可能不是有意的):

通过使用onTouchStart检测用户何时按下可拖动元素,可以在正确的时间禁用滚动。

触摸持续时间

但这还不是全部!您如何知道用户是否想要滚动或拿起一个组件?为此,可以使用检测触摸持续时间:

  • 保持时激活:如果用户触摸并 按住可拖动组件上的相同位置,则激活拖动。
  • Ignore on swipe:如果触摸持续时间很短,例如滑动,我们可以猜测用户正在滚动。

我的下一步

现在我可以在桌面上进行拖放(在弹出菜单栏内——这是另一个问题),我正在改善我的编辑器在小屏幕上的体验。

我正在探索的一个想法是使拖放菜单可以隐藏,因此整个空间都可以用于编辑。这是一个漫威原型:

感谢您的阅读,如果您有任何问题或希望我更详细地介绍,请发表评论。另外,在此处了解有关我正在构建的电子邮件设计工具的更多信息。

来源:https://prototypr.io/post/building-drag-drop-ui


0