From d22da1dc28f7f7247c4cc4aae011ace235e1ecd1 Mon Sep 17 00:00:00 2001 From: jesco-absolut Date: Sat, 4 Jul 2026 01:39:13 -0400 Subject: [PATCH] fix(handler): clear hovered state after mouseout. close #1035 --- src/Handler.ts | 2 ++ test/ut/spec/Handler.test.ts | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 test/ut/spec/Handler.test.ts diff --git a/src/Handler.ts b/src/Handler.ts index 45b09ceef..9fc71559c 100644 --- a/src/Handler.ts +++ b/src/Handler.ts @@ -243,6 +243,8 @@ class Handler extends Eventful { this.dispatchToElement(this._hovered, 'mouseout', event); } + this._hovered = new HoveredResult(0, 0); + if (eventControl !== 'no_globalout') { // FIXME: if the pointer moving from the extra doms to realy "outside", // the `globalout` should have been triggered. But currently not. diff --git a/test/ut/spec/Handler.test.ts b/test/ut/spec/Handler.test.ts new file mode 100644 index 000000000..103d480fc --- /dev/null +++ b/test/ut/spec/Handler.test.ts @@ -0,0 +1,62 @@ +import Handler from "../../../src/Handler"; +import Storage from "../../../src/Storage"; +import { Rect } from "./zrender"; + +function makeEvent(zrX: number, zrY: number) { + return { + zrX, + zrY, + zrDelta: 0, + zrByTouch: false, + which: 1, + } as any; +} + +describe("Handler", function () { + it("should fire mouseover again after mouseout from canvas and re-entering the same element", function () { + const storage = new Storage(); + const proxy = { + on() {}, + dispose() {}, + setCursor() {}, + } as any; + const painter = { + getWidth() { + return 200; + }, + getHeight() { + return 200; + }, + } as any; + const handler = new Handler(storage, painter, proxy, null, null); + + const rect = new Rect({ + shape: { + x: 0, + y: 0, + width: 100, + height: 100, + }, + }); + storage.addRoot(rect); + + let mouseoverCount = 0; + let mouseoutCount = 0; + rect.on("mouseover", function () { + mouseoverCount++; + }); + rect.on("mouseout", function () { + mouseoutCount++; + }); + + handler.mousemove(makeEvent(10, 10)); + expect(mouseoverCount).toBe(1); + expect(mouseoutCount).toBe(0); + + handler.mouseout(makeEvent(150, 150)); + expect(mouseoutCount).toBe(1); + + handler.mousemove(makeEvent(10, 10)); + expect(mouseoverCount).toBe(2); + }); +});