在画布中拖动对象

16

我正在寻找一种简单易用的方法,可以将拖动行为分配给画布中的多个对象(图像、形状等)。是否有人知道任何好的方法或库,可以让对象四处拖动?谢谢


你想拖动哪些形状,圆形、方框、多边形?每种形状的操作略有不同。 - Zevan
我还没有尝试过形状。现在我只是试图弄清楚如何拖动我添加到画布上的图像。 - Rigil
5个回答

19

创建自己的鼠标事件需要一些工作,理想情况下,您应该创建或使用某种迷你库。我计划在不久的将来创建类似于这样的东西。无论如何,我在jsFiddle上创建了一个拖放演示,展示了如何拖动图像 - 您可以在这里查看它

您可以像这样创建可拖动的图像:

var myImage = new DragImage(sourcePath, x, y);

如果您对此有任何问题,请告诉我。希望能帮到您。

编辑

在拖动多个图片时存在一个错误。这里是新版本

另外一个您可能想要了解的是easeljs,它类似于AS3的风格……鼠标事件、拖放等等。


尝试了你的演示,暂时看起来很不错。谢谢。 - Rigil
当您添加更多图像时,我注意到了一些奇怪的行为。我想应该有一种方法来确保每次只拖动一个图像。 - Rigil
你可能可以用一个变量来解决这个问题... 一个布尔值... 让我看一下,然后我会更新我的答案。 - Zevan
没问题 :) - 我刚刚更新了一下...它仍然需要一些z排序。http://jsfiddle.net/Zevan/QZejF/5/ - Zevan
@Zevan 你有没有想法为什么这在Firefox 3.6中不起作用?我在firebug中得到一个错误,指向“c.drawImage(img,that.x,that.y);”这一行。 - Rigil
2
是的...我有一个坏习惯,即使它在任何浏览器中都几乎不起作用,也会使用offsetX/Y....只需更改为clientX和clientY,问题就应该得到解决:http://jsfiddle.net/QZejF/10/如果您需要将画布放置在舞台的左上角以外的其他位置-您需要编写更多代码,如果您需要,我可以发布-让我知道。 - Zevan

14
HTML Canvas 与 SVG 或 HTML 不同,使用非保留(或即时)图形 API。这意味着,当你在画布上绘制一些东西(如图像)时,不会留下有关该物体的任何知识。剩下的只有画布上的像素,混合了所有先前的像素。你无法真正地拖动像素的子集;首先,它们所在的像素已经消失了。你需要做的是:
  1. 跟踪 mousedown 事件并查看其是否位于拖动的“正确”位置。(你将需要跟踪哪些图像 / 对象在哪里,并执行鼠标命中检测。)
  2. 当用户拖动鼠标时,从头开始重新绘制整个画布,每次根据当前鼠标位置和初始 mousedown 位置之间的偏移量,在新位置上绘制图像。
一些我可能建议的替代方法:
  • SVG
  • Pure HTML
  • 多层画布,将一个透明画布拖动到另一个画布上面。
HTML Canvas 非常适合许多事情。用户与似乎是不同的“元素”进行交互(但实际上并不是)不是其中之一。
更新:以下是一些展示画布拖动的示例: 但是,它们都没有为你创建跟踪形状的单独库。

我明白了,感谢您的澄清。我的计划是最终将我的代码转换成一个简单的游戏。我想继续使用canvas,因为听起来canvas在未来会有更多的浏览器支持。目前,我不介意按照您上面概述的步骤进行操作,但理想情况下,我希望找到一个库,可以插入我的代码中,帮助我处理元素的鼠标交互。 - Rigil
@Rigil - 我同意Phrogz的观点。当我第一次听说canvas时,我认为它会像一个可以在没有flash的情况下使用的flash表面。然而正如他所说,画布上没有“对象”的层次结构,只有一个大的像素集合。移动一个东西,你就需要清除画布并重新绘制所有内容。 - UpTheCreek

4

KineticJS是一种JavaScript库,您可以专门用于动画。

以下是链接:html5canvastutorials


2

Canvas 和 jCanvas

你绝对需要查看 jCanvas。它是一个超级干净的 Canvas 包装器,可以在不增加代码复杂性的情况下打开许多门。它使得像这样的事情变得非常容易。

例如,这里有一个小型沙盒,非常接近你所需求的功能,带有拖拽和重绘功能:

在两个元素之间绘制箭头

Drawing an arrow

我曾尝试使用DIV和jQuery完成所有事情,但它在交互性和质量方面总是不足。希望这能帮助像我一样的其他人。JP

两个元素之间绘制箭头似乎出了问题? - fatfrog
@fatfrog 你说得对。似乎沙盒的链接不再正确地填充代码了。我希望我已经将代码复制到答案中了。嗯,你绝对想要检查 jCanvas 作为解决方案,并且如果有人重新编写此示例的代码,请更新此答案。 - Joshua Pinter
你尝试过Fabric.js吗?你会如何将其与jCanvas进行比较? - fatfrog
1
@fatfrog 没有。这个答案是5年前的,不确定那时是否有该工具。但我们仍在使用 jCanvas,它非常出色。 - Joshua Pinter

1
当你创建新的对象,无论是窗口、卡片、形状还是可拖动的图像时,你可以将它们存储在“当前未被选中的对象”数组中。当你单击它们或选择它们或开始拖动它们时,你可以将它们从“未选中的对象”数组中删除。这样,你就可以通过检查它是否被选中来控制在特定的mousedown事件或mousemove事件中可以移动什么。如果它被选中,它将不在“未选中”数组中,你可以在拖动形状时将鼠标指针移到其他形状上而不会将它们拖动。
创建你想要拖动的对象数组也有助于层次结构。画布最后绘制属于前景对象的像素。因此,如果对象在一个数组中,你只需要在迭代数组并绘制存储在数组元素中的对象时,切换它们的实例,例如从objectArray[20] 到 objectArray[4],你可以更改其他对象是否显示在其他对象的顶部或后面。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接