如何实现DOM向Phaser场景传递鼠标指针移动事件?
Got it, let's break down how to fix this issue where your Phaser scene stops tracking mouse movement once the cursor leaves the canvas area. Here are a couple of straightforward, practical approaches to sync DOM mouse events with your Phaser input system:
Approach 1: Global DOM Listener + Coordinate Conversion
The simplest way is to listen for mouse movement across the entire document, translate those page-level coordinates into Phaser canvas-relative values, and manually update Phaser's active pointer state. This keeps your existing mouse-tracking logic working seamlessly even when the cursor is outside the scene.
Step-by-Step Implementation
- Set up the global listener in your scene's
createmethod:
function create() { // Grab a reference to the Phaser game canvas const gameCanvas = this.sys.game.canvas; // Store the handler on the scene instance for easy cleanup later this.globalMouseMoveHandler = (event) => { // Calculate the canvas's position relative to the viewport const canvasRect = gameCanvas.getBoundingClientRect(); // Convert mouse position from page coordinates to canvas-relative values const canvasX = event.clientX - canvasRect.left; const canvasY = event.clientY - canvasRect.top; // Update Phaser's active pointer with the converted coordinates const activePointer = this.input.activePointer; activePointer.x = canvasX; activePointer.y = canvasY; // Optional: Manually trigger the 'pointermove' event to activate existing listeners this.input.emit('pointermove', activePointer); }; // Attach the listener to the document document.addEventListener('mousemove', this.globalMouseMoveHandler); }
- Clean up the listener when the scene shuts down to avoid memory leaks:
function shutdown() { // Remove the global mouse listener document.removeEventListener('mousemove', this.globalMouseMoveHandler); }
Why This Works
Phaser's input system relies on its internal pointer state. By updating activePointer.x and activePointer.y with the converted coordinates, you're making Phaser think the mouse is still interacting with the canvas. Emitting the pointermove event ensures any existing this.input.on('pointermove', ...) handlers in your scene will fire as expected.
Approach 2: Extend Phaser's Input System (Advanced)
If you need this global mouse tracking across multiple scenes, you can create a custom plugin to extend Phaser's input system and automate the process:
class GlobalInputPlugin extends Phaser.Input.InputPlugin { boot() { super.boot(); this.globalMouseHandler = (event) => { const canvasRect = this.game.canvas.getBoundingClientRect(); const x = event.clientX - canvasRect.left; const y = event.clientY - canvasRect.top; this.activePointer.x = x; this.activePointer.y = y; this.emit('pointermove', this.activePointer); }; document.addEventListener('mousemove', this.globalMouseHandler); } shutdown() { document.removeEventListener('mousemove', this.globalMouseHandler); super.shutdown(); } } // Register the plugin in your game config const config = { type: Phaser.AUTO, // ... other game config options plugins: { global: [ { key: 'GlobalInput', plugin: GlobalInputPlugin, start: true } ] } };
This way, every scene in your game will automatically track global mouse movement without repeating code.
Key Notes
- Coordinate Accuracy: Using
getBoundingClientRect()accounts for page scrolling and canvas scaling, so your converted coordinates will always be accurate relative to the Phaser canvas. - Additional Mouse States: If you need to track other mouse actions (like clicks or releases), you can add similar listeners for
mousedown,mouseup, etc., and update the corresponding properties onactivePointer(likeisDown).
内容的提问来源于stack exchange,提问作者Benjamin McFerren

