简体   繁体   English

HTML5 canvas hittest任意形状

[英]Html5 canvas hittest arbitrary shape

I'm trying to develop program which can render images and text in canvas. 我正在尝试开发可以在画布中渲染图像和文本的程序。 I tried to handle click on image in canvas, but it work for rectable images. 我试图处理画布中的图像单击,但是它适用于可恢复的图像。

My question: Did you know solution or frameworks for handle click on visible part of image (not transparent part) in canvas ? 我的问题:您是否知道用于处理的解决方案或框架会单击画布中图像的可见部分(而不是透明部分)?

I'm looking for javascript implementation of ActionScript hitTestObject function, if someone familiar with it. 如果有人熟悉,我正在寻找ActionScript hitTestObject函数的javascript实现。

Here is simple algorithm with rectable hit text: http://jsfiddle.net/V92Gn/298/ 这是带有可点击文本的简单算法: http : //jsfiddle.net/V92Gn/298/

var hitted = e.clientX >= position.x && 
    e.clientX <= position.x + logoImg.width && 
    e.clientY >= position.y && 
    e.clientY <= position.y + logoImg.height;

Solution using pure JavaScript + canvas 使用纯JavaScript + canvas的解决方案

For cases where the hit target is mixed with the background you can do two things: 对于命中目标与背景混合的情况,您可以做两件事:

  1. Create a separate canvas which is stacked on top of the main canvas, draw the target object on that and do the testing of that canvas. 创建一个单独的画布,该画布堆叠在主画布的顶部,在该画布上绘制目标对象,然后对该画布进行测试。
  2. Create an off-screen canvas which contains the target object isolated and test on that 创建一个屏幕外画布,其中包含隔离的目标对象并在该对象上进行测试

In this example I will use an off-screen canvas. 在此示例中,我将使用屏幕外的画布。

What we do is to basically replicate the image by creating an off-screen canvas the size of the image and draw in the image when loaded. 我们要做的是通过创建与图像大小相同的屏幕外画布来基本复制图像,并在加载时绘制图像。 This will protect the background and keep it transparent no matter what is on the main canvas: 无论主画布上有什么内容,这都将保护背景并保持背景透明:

Modified fiddle here 在这里修饰小提琴

/// create an off-screen canvas to hold image
var ocanvas = document.createElement('canvas');
var octx = ocanvas.getContext('2d');

logoImg.onload=function(){

    /// set off-screen canvas to same size as image
    ocanvas.width = this.width;
    ocanvas.height = this.height;
    octx.drawImage(this, 0, 0);

    ... rest of code

Then using your existing code but with an adjustment for mouse position we can use the hitted variable you use to first check if we are inside the target object. 然后使用您现有的代码,但对鼠标位置进行调整,我们可以使用您用来首先检查我们是否在目标对象内部的hitted变量。

$(canvas).on('mousemove', function(e) {

    /// correct mouse position so it becomes relative to canvas
    var r = canvas.getBoundingClientRect(),
        x = e.clientX - r.left,
        y = e.clientY - r.top;

     var hitted = x >= position.x && x <= position.x + logoImg.width &&
                  y >= position.y && y <= position.y + logoImg.height;

Now that we know we are inside the rectangle we can extract a pixel from the off-screen canvas by compensating for the object position: 现在我们知道我们在矩形内部,可以通过补偿对象位置从屏幕外的画布中提取一个像素:

    if (hitted === true) {
        /// extract a single pixel at the adjusted position
        var pixel = octx.getImageData(x - position.x, y - position.y, 1, 1).data;

        /// set hitted again based on alpha value is 0 or not
        hitted = pixel[3] > 0;
    }

    ...

As you can see in the modified fiddle we only change the class you use to red when we are on an actual pixel in the target no matter what the background of it is (when drawn separately). 正如您在修改的小提琴中看到的那样,无论目标背景是什么(分别绘制),只要我们将其放在目标中的实际像素上,我们都将其更改为红色。

Finally a couple of words on CORS: In this case, as you use DropBox, you can request CORS usage of the image simply by activating the crossOrigin property on the image object before you set the source: 最后,关于CORS的几句话:在这种情况下,当您使用DropBox时,只需在设置源之前激活图像对象上的crossOrigin属性,即可请求对图像进行CORS使用:

logoImg.crossOrigin = '';   /// this is the same as setting anonymous
logoImg.src="http://dl.dropbox.com/..."; 

As DropBox (and image sharing sites such as ImgUr.com) support CORS usage they will allow the request and we can therefor extract pixels from the image. 由于DropBox(以及ImgUr.com等图像共享网站)支持CORS使用,因此它们将允许该请求,因此我们可以从图像中提取像素。

If the servers didn't allow it however we wouldn't be able to do this. 如果服务器没有答应但我们不能够做到这一点。 To be sure CORS is ok you should host the image in the same domain as the page when you release it. 为确保CORS正常,发布图像时,应将其托管在与页面相同的域中。

I recommend using EaselJS which has a hitTest method similar to how it works in Actionscript: 我建议使用EaselJS ,它具有一个hitTest方法,类似于在Actionscript中的工作方式:

myDisplayObject.hitTest(localX, localY);

Here you can find some demos that show the technique: http://shallaazm.com/createjs/easeljs/tutorials/HitTest/ 在这里,您可以找到一些演示该技术的演示: http : //shallaazm.com/createjs/easeljs/tutorials/HitTest/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM