konvajskonva

Is it possible to register Konva Events during the Capture Phase?


I'm attempting to register a click event on the Konva Stage within the Capture Phase of the event phases and having no luck ...

Here is a JSFiddle which demonstrates my issue. There are ten click events registered; two for each element - one of which being for the capture phase and the other for the bubbling phase. I understand that "Konva events are not DOM events" and, for the code example, this explains why all of the Konva events fire before any of the DOM events. However, from the output of clicking the green circle, you see that the Konva Events don't recieve the useCapture parameter from the addEventListener and are always fired in the Bubbling Phase.

I am aware that you can use the on keyword to register events for Konva Elements but haven't seen a way to register these during the capture phase whereas the addEventListener seems like it could work with the useCapture parameter.

The end goal to be able to register a click event on the Konva Stage within the Capture Phase before it is then handled by the Konva Shape click event handler. Is this possible?

var container = document.getElementById("container")
var div, canvas

var stage = new Konva.Stage({
  container: container.id,
  width: window.innerWidth,
  height: window.innerHeight,
  listening: true,
})

var layer = new Konva.Layer()
stage.add(layer)

var circle = new Konva.Circle({
  x: stage.width() / 2,
  y: stage.height() / 2,
  width: 50,
  height: 50,
  fill: "green",
})

layer.add(circle)

div = container.firstChild // Konva creates another div with classname: "konvajs-content" to place the Canvas within
canvas = div.firstChild // This is the Canvas that Konva creates

container.addEventListener("click", (e) => handleEvent(e, container), true)
div.addEventListener("click", (e) => handleEvent(e, div), true)
canvas.addEventListener("click", (e) => handleEvent(e, canvas), true)
stage.addEventListener("click", (e) => handleEvent(e, stage), true)
circle.addEventListener("click", (e) => handleEvent(e, circle), true)

circle.addEventListener("click", (e) => handleEvent(e, circle), false)
stage.addEventListener("click", (e) => handleEvent(e, stage), false)
canvas.addEventListener("click", (e) => handleEvent(e, canvas), false)
div.addEventListener("click", (e) => handleEvent(e, div), false)
container.addEventListener("click", (e) => handleEvent(e, container), false)

function handleEvent(e, element) {
  if (element.nodeName) {
    // HTML Element
    console.log(
      `Target: ${element.nodeName} ${element.className} -->  Capture: ${e.eventPhase == 1}, Target: ${e.eventPhase == 2}, Bubble: ${e.eventPhase == 3}`,
    )
  } else if (element.nodeType) {
    // Konva Element
    console.log(
      `Target: ${element.nodeType}  -->  Capture: ${e.eventPhase == 1}, Target: ${e.eventPhase == 2}, Bubble: ${e.eventPhase == 3}`,
    )
  }
}
<script src="https://unpkg.com/konva@9.3.22/konva.min.js"></script>
<div id="container" class="container"></div>


Solution

  • That is not possible with current Konva API.

    Konva has no capture phase. Events only bubble (shape -> group -> layer -> stage). And addEventListener on Konva nodes is just an alias of node.on(...), so useCapture is ignored.