有没有一种方法可以轻松确定画布中绘制的形状已被单击?
我现在正在学习如何使用 HTML5 画布。我有一个简单的脚本,可以沿水平线绘制圆圈。
我想增强我的脚本以更具交互性。我希望能够单击沿线的一个圆圈,这会导致链接到该圆圈的数据在画布上显示为文本。
这在画布上很容易实现吗?从我看过的教程中我发现我必须在画布本身上放置一个 onclick 。从那里我猜测我必须找出我的鼠标光标被单击的位置,并以某种方式找出哪个圆圈包含我的单击点。
有没有任何代码片段或指针可以帮助我解决这个问题?或者,画布真的不适合此类问题吗?非常感谢任何评论。
I am learning how to use the HTML5 canvas right now. I have a simple script which draws circles along a horizontal line.
I would like to enhance my script to be more interactive. I want to be able to click on one of the circles along the line and this causes the data linked to that circle to be shown as text on the canvas.
Is this easily achieveable in the canvas? From the tutorials I have looked at I gather that I have to put an onclick on the canvas itself. From there I was guessing that I would have to work out where my mouse cursor has been clicked and somehow work out which circle contains my clicked point.
Are there any snippets of code or pointers that can help me with this? Alternatively, is the canvas really not suitable for this type of problem? Any comments are very much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以使用canvas的isPointInPath方法添加鼠标事件处理。像下面这样的东西(未经测试)。
这将识别任何形状,如果您要绘制矩形和圆形以外的任何形状,这将非常有用。然而,这样做的主要缺点是您必须在每次单击时重新绘制(如果要添加鼠标悬停,则必须重新绘制鼠标移动)。根据我的经验,在开始看到性能问题之前,我至少可以绘制 300 个对象。
我还应该注意到,isPointInPath 的 firefoxes 实现中存在一个 bug ,该错误仍未修复出于某种原因。但幸运的是,修复很简单,
只需将 ctx.isPointInPath(x,y) 替换为 ctx.isPointInPath_mozilla(x,y) 即可,一切正常
You can add mouse event handling by using the isPointInPath method of canvas. Something like this below (untested).
This will recognize any shape, which is very useful if you are drawing anything other than rectangles and circles. However, the major drawback to this is that you have to redraw on every click (or mousemove if you are adding mouseovers). In my experience I can get away with drawing at least 300 objects before I start seeing issues with performance.
I should also note there is a bug in firefoxes implementation of isPointInPath that remains unfixed for some reason. But happily the fix is easy enough
just replace ctx.isPointInPath(x,y) with ctx.isPointInPath_mozilla(x,y) and everything works
Canvas 使用光栅图形。一旦你画了一个圆,它就不再具有圆的身份——你只有一堆像素。您需要自己跟踪所有形状。
如果您使用矢量图形(例如 SVG),则形状会保留身份并且可以进行操作。这样可能会更容易。
Canvas uses raster graphics. Once you have drawn a circle, it no longer has an identity as a circle - you just have a bunch of pixels. You need to keep track of all shapes yourself.
If you use vector graphics, like SVG, the shapes retain an identity and can be manipulated. It's probably going to be easier this way.
您为画布创建单击事件,并且在处理程序中,如果用户单击圆圈,则必须计算(一些基本数学)。另一种方法是不使用画布,而是使用 SVG,像 raphael 这样的库可能会有所帮助。
You create click event for canvas and in handler you must calculate (some basic math) if user click on the circle. The other way is not to use canvas but SVG there are libraries like raphael that can be helpful.
我已经为移动设备画布绘制完成了类似的操作,然后进行形状匹配。
我的程序是。
根据画布高度和宽度(以像素为单位)的数量声明一个 2D 数组。
用 0 填充数组
对于 mousemove 事件(桌面浏览器)跟踪位置。您将获得 X,Y 值。
在你的二维数组中,在行和列中放入 1(X 和 Y 值)。
绘制完成后,您将得到一个二维二值图像数组。
现在有趣的部分:
尝试图像动量或此链接中的任何其他合适的方法。 http://www. imageprocessingplace.com/downloads_V3/root_downloads/tutorials/Tutorial--Algorithms%20for%202-D%20Object%20Recognition.pdf
如果您保存一些 2D 绘制的形状数组并与当前绘制的图像匹配,您将能够找到最近的匹配项。如果用户绘制了完全不同的形状,请尝试找到合适的阈值。
我希望这会有所帮助。
I've done something like this for mobile device canvas drawing and then shape matching.
My procedure was.
Declare a 2D array based on the number of canvas height and width in pixels.
Fill the Array with 0
For the mousemove event (Desktop browser) track the position. You will get a X,Y Value.
in your 2D array put 1 in row and column (X and Y value).
After drawing you will get a 2D binary image Array.
Now the fun part:
Try Image momentam or any other suitable method from this link. http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/Tutorial--Algorithms%20for%202-D%20Object%20Recognition.pdf
If you save some 2D drawn shapes array and match with the current drawn image, you will be able to find a nearest match. Try to find a suitable threshold if user drawn a completely different shape.
I hope that will help.