Merge pull request #1933 from konvajs/codex/resolve-mouseleave-vs-pointerleave-behavior
Some checks failed
Test Browser / build (20.x) (push) Has been cancelled
Test NodeJS / build (23.x) (push) Has been cancelled

Fix pointerleave bubbling behavior
This commit is contained in:
Anton Lavrenov 2025-06-05 16:18:06 -05:00 committed by GitHub
commit 27fc1b1ba5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 2 deletions

View File

@ -88,6 +88,10 @@ const ABSOLUTE_OPACITY = 'absoluteOpacity',
LISTENING = 'listening',
MOUSEENTER = 'mouseenter',
MOUSELEAVE = 'mouseleave',
POINTERENTER = 'pointerenter',
POINTERLEAVE = 'pointerleave',
TOUCHENTER = 'touchenter',
TOUCHLEAVE = 'touchleave',
NAME = 'name',
SET = 'set',
SHAPE = 'Shape',
@ -2335,8 +2339,17 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
evt.target = this;
}
const nonBubbling = [
MOUSEENTER,
MOUSELEAVE,
POINTERENTER,
POINTERLEAVE,
TOUCHENTER,
TOUCHLEAVE,
];
const shouldStop =
(eventType === MOUSEENTER || eventType === MOUSELEAVE) &&
nonBubbling.indexOf(eventType) !== -1 &&
((compareShape &&
(this === compareShape ||
(this.isAncestorOf && this.isAncestorOf(compareShape)))) ||
@ -2347,7 +2360,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
// simulate event bubbling
const stopBubble =
(eventType === MOUSEENTER || eventType === MOUSELEAVE) &&
nonBubbling.indexOf(eventType) !== -1 &&
compareShape &&
compareShape.isAncestorOf &&
compareShape.isAncestorOf(this) &&

View File

@ -8,6 +8,7 @@ import {
simulateTouchStart,
simulateTouchMove,
simulateTouchEnd,
simulatePointerMove,
compareCanvases,
createCanvas,
showHit,
@ -1222,6 +1223,36 @@ describe('Stage', function () {
assert.equal(count, 2);
});
it('stage pointerleave should not fire when leaving a child', function () {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var circle = new Konva.Circle({
fill: 'red',
radius: 30,
x: 50,
y: 50,
});
layer.add(circle);
layer.draw();
var stageLeave = 0;
var circleLeave = 0;
stage.on('pointerleave', function () {
stageLeave += 1;
});
circle.on('pointerleave', function () {
circleLeave += 1;
});
simulatePointerMove(stage, { x: 50, y: 50 });
simulatePointerMove(stage, { x: 90, y: 50 });
assert.equal(circleLeave, 1, 'circle pointerleave should fire');
assert.equal(stageLeave, 0, 'stage pointerleave should not fire');
});
it('toDataURL with hidden layer', function () {
var stage = addStage();
var layer = new Konva.Layer();