【问题标题】:Html5 canvas hittest arbitrary shapeHtml5 canvas hittest 任意形状
【发布时间】:2013-11-06 08:19:50
【问题描述】:

我正在尝试开发可以在画布中呈现图像和文本的程序。我试图处理画布中的图像点击,但它适用于可调整的图像。

我的问题:您知道处理点击画布中图像可见部分(非透明部分)的解决方案或框架吗?

如果有人熟悉的话,我正在寻找 ActionScript hitTestObject 函数的 javascript 实现。

这是带有可调整命中文本的简单算法: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;

【问题讨论】:

  • 请分享您目前尝试过的代码。小提琴会很棒。您可以通过抓取一个像素来测试图像的透明度并比较其 alpha 值。但这里 CORS 将适用。
  • 对于 CORS,Ken 的意思是跨域资源共享。如果您从其他域下载图像,则适用。
  • jsfiddle.net/V92Gn/301 - 红色匹配,由于 CORS,在小提琴中不可能透明。 p.s. Fiddle 应该托管更多图像进行测试...
  • 如果画布中的图像来自其他域,为什么 CORS 不允许使用 getImageData。浏览器中此安全规则的原因是什么?

标签: javascript canvas hittest


【解决方案1】:

使用纯 JavaScript + canvas 的解决方案

对于命中目标与背景混合的情况,您可以做两件事:

  1. 创建一个单独的画布,堆叠在主画布的顶部,在其上绘制目标对象并对该画布进行测试。
  2. 创建一个屏幕外画布,其中包含隔离的目标对象并在其上进行测试

在本例中,我将使用离屏画布。

我们所做的基本上是通过创建一个与图像大小相同的屏幕外画布并在加载时在图像中绘制来复制图像。无论主画布上是什么,这将保护背景并使其保持透明:

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

然后使用您现有的代码,但通过调整鼠标位置,我们可以使用 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;

现在我们知道我们在矩形内,我们可以通过补偿对象位置从屏幕外画布中提取一个像素:

    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;
    }

    ...

正如您在修改后的小提琴中所见,我们仅在目标中的实际像素上将您使用的类更改为红色,无论其背景是什么(单独绘制时)。

关于CORS的最后几句话:在这种情况下,当您使用DropBox时,您可以通过在设置源之前激活图像对象上的crossOrigin属性来请求图像的CORS使用:

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

由于 DropBox(以及 ImgUr.com 等图像共享网站)支持 CORS 使用,它们将允许请求,因此我们可以从图像中提取像素。

如果服务器不允许允许,但是我们将无法做到这一点。为确保 CORS 正常,您应该在发布时将图像托管在与页面相同的域中。

【讨论】:

    【解决方案2】:

    我建议使用EaselJS,它的 hitTest 方法类似于它在 Actionscript 中的工作方式:

    myDisplayObject.hitTest(localX, localY);
    

    您可以在这里找到一些展示该技术的演示: http://shallaazm.com/createjs/easeljs/tutorials/HitTest/

    【讨论】:

      猜你喜欢
      • 2012-03-30
      • 1970-01-01
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      • 2015-08-09
      • 2014-11-27
      • 2011-05-22
      • 2012-03-13
      相关资源
      最近更新 更多