【问题标题】:Swap draggable element to mouse cursor on drop of another draggable在放置另一个可拖动元素时将可拖动元素交换为鼠标光标
【发布时间】:2014-03-07 17:24:53
【问题描述】:

我见过几个关于在放置时交换两个可拖动元素的问题,但我的情况有点不同。

基本上,我在(非线性)网格中布置了一堆可拖动元素。在许多情况下,网格将完全填充数据。我们希望允许用户轻松地重新排列网格元素,但由于网格是非线性的,使用“可排序”不是一种选择。而且由于网格已完全填充,当一个网格位置被拖到另一个网格位置时直接交换两个网格位置并不是理想的解决方案(因为我们并不是试图将三个位置重新排列成某种脑筋急转弯)。

我们想要做的是在拖动网格元素(称为 A)时发生正常的“拖动”操作,但是当元素被拖放到所需的目标(其中已经有另一个网格项)时,称为 B),然后 A 应该取代 B 的位置,然后 B 应该“捕捉”鼠标光标,就像用户单击并拖动它一样。这显然会稍微弄乱鼠标交互,因为现在用户没有按下鼠标按钮,而是在拖动一个元素,所以要释放元素,他要么单击 A 来自的空单元格,要么单击另一个网格元素 C ,此时 B 将取代 C 的位置,C 现在将“附加”到鼠标光标上。

我仔细研究了“可拖动”文档和源代码,似乎没有办法完全按照我想要的方式配置它,但我很确定我可以扩展可拖动小部件并覆盖它的几个方法来实现我想要的,而不必从头开始编写我自己的解决方案。如果它使它变得更容易,那么与拖动事件相比,用于触发拖动的鼠标事件是否是单击对我来说真的无关紧要。

要清楚,这是我正在寻找的一种交互图:

Original Setup - ^ is mouse cursor
[A]  ^  [C]
[B]     [D]

Now click and drag on A. Result is:
[ ]^A   [C]
[B]     [D] 

Now drag over B and release. Result is:
[ ]     [C]
[A]^B   [D]

B is now acting as if it's being dragged, but mouse button is not held down. Move
cursor over C and click mouse button. Result is:
[ ]     [B] ^C
[A]     [D]

B has taken C's place, and C is now following the mouse cursor. Again, mouse 
button is not being held down. Move cursor over empty cell and click mouse 
button. Result is:
[C] ^   [B]
[A]     [D]

Now there is nothing attached to the mouse cursor.

【问题讨论】:

  • 在真正尝试实现这一点之前,我会在ux.stackexchange.com(用户体验)中四处询问,因为我觉得这有点烦人,你可能混淆用户。也许他们会更习惯于定期交换
  • 谢谢,但是交互已经通过了测试,无论如何这都是针对“训练有素的”用户群的——有了正确的反馈和可供性,我们的测试用户就可以毫不费力地弄清楚这一点。不过我很欣赏这个建议。
  • 澄清一下,这实际上是一个“括号”风格的游戏,其中可能有 128 名参赛者,分为两列,每列 64 人。使用“可排序”是不可能的,因为实际上有许多不同的固定大小的列表,“溢出”一个列表会让我回到这个位置。我们尝试了交换,但因为你实际上不能一次看到所有团队以获得一个大括号,当交换导致一个团队“消失”(因为它交换到屏幕外的位置)时,用户会感到困惑。交换奇数个位置也比我们的用户喜欢的要困难。

标签: javascript jquery jquery-events jquery-ui-draggable jquery-ui-droppable


【解决方案1】:

好吧,由于没有人尝试回答我的问题,我设法找到了一种相当简单的方法来自己完成这个任务。在这种情况下,我的救星原来是 jquery.simulatejquery.simulate.extjquery.simulate.drag-n-drop 插件。使用这些在一组元素(或者在拖放插件的情况下,单个元素)上模拟特定的本机浏览器事件是微不足道的。这意味着我可以简单地使用来自 jQueryUI droppable 的“drop”回调来完成我需要的:

drop: function (e, ui) {
    var $targ = $(e.target);
    ui.draggable.detach().appendTo($targ).css({top: 0, left: 0});
    $targ.find('.ui-draggable .handle').simulate('drag', {});
}

就是这样!这就是全部。这是一个演示实际解决方案的小提琴:http://jsfiddle.net/isochronous/mD8uM/

更新:事实证明,在可拖动中处理“还原”行为实际上是最难的部分。我最终创建了自己的小部件,它扩展了$.ui.draggable 来处理这个问题。我更新了小提琴并添加了 cmets 来解释它是如何工作的,以防万一有人感兴趣。

【讨论】:

  • 不错的解决方案 - 但仍然有一个错误:抓住左侧的 Item1List1 - 现在将它拖动到两个列表之间的中心一点 - 你的鼠标仍然在左侧项目上,而项目在右侧有点多。如果您现在放手,该项目将与右侧的项目交换。如果您随后放入无效位置,则拖动的项目也会向右移动 - 一个字段中有两个项目:-o
  • 感谢您的错误报告 - 我已经看到了类似的问题,这也是我选择在其他答案中发布的替代解决方案的原因之一。
【解决方案2】:

将此作为单独的答案添加,因为它是解决问题的完全不同的方法。

在我完成这项工作后,我尝试添加一些其他新功能,例如将is-swap 类应用于悬停在非空droppable 上的可拖动对象,并在悬停时对其应用is-drop 类在一个空的。但是因为我们的 droppable 非常接近,所以 overout 回调会在成为 over 一个新的 droppable 之前变得混乱,然后再成为前一个的 out

我已经意识到,如果我希望继续使用 jQuery UI,我需要做的不是子类可拖动或可放置,而是完全使用它们新的小部件。 Draggable 和 droppable 都是在许多不同元素上实例化的小部件(例如,每个 draggable 都是它自己的实例,每个 droppable 都是它自己的实例),但我需要的是 包含的 一个 小部件 许多可拖动和可放置。这将使它们在相互交互时更容易控制它们的状态。

现在我的计划是创建一个可以在某种容器元素上实例化的小部件,并提供允许小部件使用者将所需元素定位为可拖动和可放置的选项,并简单地利用可拖动和可放置他们的“自然”状态。这将允许我做一些事情,比如从另一个回调中检查一个 droppable 的状态,并修复我之前提到的 outover 计时问题。

我将在接下来的几天内尝试实现这一点,一旦我有东西要显示,我会更新这个答案。

更新:这里是使用这种方法的更简单、更准确的实现。 http://jsfiddle.net/isochronous/BQyx2/

【讨论】:

    猜你喜欢
    • 2022-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多