简体   繁体   English

动画形状内的KineticJS单击检测

[英]KineticJS click detection inside animated shapes

OK, I admit I tried to be clever: I thought if I overrode Shape's drawFunc property I could simply draw whatever inside a rectangle and still use KineticJS's click detection. 好的,我承认我试图变得聪明:我想,如果我覆盖Shape的drawFunc属性,我可以简单地在矩形内绘制任何内容,并且仍然使用KineticJS的点击检测。 Here's my attempt: 这是我的尝试:

var shape = new Kinetic.Shape({
  drawFunc: function(context) {
    var id = 26;  // Id of a region inside composite image.
    context.beginPath();
    context.rect(0, 0, w, h);
    context.closePath();
    this.fill(context);
    this.stroke(context);
    context.drawImage(copyCanvas, (id % 8) * w, flr(id / 8) * h, 
        w, h, 0, 0, w / 2, h / 2);
  },
  draggable: true
});

So, the idea was to draw a rectangle, and use drawImage() to draw something on top of the rectangle (like a texture, except it changes from time to time because copyCanvas itself changes). 因此,该想法是绘制一个矩形,并使用drawImage()在矩形顶部绘制一些内容(类似于纹理,不同之处在于它会不时更改,因为copyCanvas本身会更改)。 All the meanwhile, I expected event handling (drag-n-drop, in particular) to still 'just work'. 同时,我希望事件处理(尤其是拖放)仍然可以正常工作。 Well, here's what happens: the part of the rectangle not covered by my drawImage() correctly detects clicks. 好吧,这就是发生的情况:我的drawImage()未覆盖的矩形部分可以正确检测到点击。 However, the one fourth of the rectangle that is covered by the image refuses to respond to clicks! 但是,图像所覆盖的矩形的四分之一拒绝响应点击! Now, my question is why? 现在,我的问题是为什么? I dug into the KineticJS code, and looked to me that click detection simply means drawing to a buffer and seeing if a given x, y point has non-zero alpha. 我研究了KineticJS代码,对我来说,单击检测只是意味着绘制到缓冲区并查看给定的x,y点是否具有非零的alpha。 I can't see how this could be affected by my drawing an image on top of my rectangle. 我看不到在矩形上方绘制图像会如何影响它。

Any ideas what's going on? 有什么想法吗?

OK, so I went ahead and looked at the source code. 好的,所以我继续看一下源代码。 Here's the definitive answer: 这是明确的答案:

KineticJS assigns a random and unique RGB color to each shape that's created using a global map from RGB colors to shape objects. KineticJS为使用从RGB颜色到形状对象的全局映射创建的每个形状分配随机且唯一的RGB颜色。 The draw() function of the shape is called twice: once with the 'real' canvas, and once with a 'buffer' canvas used for hit detection. 形状的draw()函数被调用两次:一次使用“真实”画布,一次使用“缓冲区”画布用于命中检测。 When using the 'buffer' canvas, KineticJS switches the stroke and fill colors to the unique RGB color of the given shape. 当使用“缓冲”画布时,KineticJS将笔触和填充颜色切换为给定形状的唯一RGB颜色。 The same 'buffer' canvas is used for all shapes on a layer. 同一“缓冲”画布用于图层上的所有形状。 Thus hit detection simply becomes reading the RGB value of a given point and looking up the corresponding shape in the global map. 因此,命中检测简单地变成了读取给定点的RGB值并在全局地图中查找相应的形状。 Now, in my example I drew an image in a way that circumvented KineticJS's juggling of colors used for hit detection. 现在,在我的示例中,我以一种规避KineticJS混杂用于命中检测的颜色的方式绘制了图像。 Thus, when I clicked on the image area, KineticJS saw some unknown RGB color on the buffer canvas with no known shape assigned to it. 因此,当我单击图像区域时,KineticJS在缓冲画布上看到一些未知的RGB颜色,但未分配任何已知的形状。

The solution is not to draw the image for the 'buffer' (or 'hit detection') phase: a simple rectangle will do. 解决方案不是在“缓冲”(或“命中检测”)阶段绘制图像:一个简单的矩形即可。 In case you're wondering, here's the correct code for the drawFunc : 如果您想知道,这是drawFunc的正确代码:

var width = 200;
var height = 100;
var myShape = new Kinetic.Shape({
  drawFunc: function(context) {
    if (layer.bufferCanvas.context == context) {
      context.beginPath();
      context.rect(0, 0, width, height);
      context.closePath();
      this.fill(context);
      this.stroke(context);
     } else {
       context.drawImage(someCanvasWithAnythingOnIt, 0, 0, width, height,
         0, 0, width, height);
     }
  }});

Can I collect my own reward? 我可以收取我自己的奖励吗?

I think your problem lies in the order. 我认为您的问题出在顺序上。 There is a depth associated with each object that you draw and the default ordering is like a stack, last drawn is on top. 您绘制的每个对象都有一个深度,默认顺序就像堆栈一样,最后绘制在最上面。 Now that you have modified the code, making 2 draws inside the shape draw function, I still think the ordering is preserved and hence, the object is not able to detect the input. 既然您已经修改了代码,在形状绘制函数中进行了2次绘制,我仍然认为顺序已保留,因此该对象无法检测到输入。 Try changing the order, ie draw image first and then the rectangle and see if the problem is solved. 尝试更改顺序,即先绘制图像,然后绘制矩形,然后看问题是否解决。 Else, share a jsFiddle for an example. 另外,以jsFiddle为例。

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

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