Spaces:
Sleeping
Sleeping
File size: 5,468 Bytes
aeb61fc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
export function initializeEraserPen(canvasElement, onEraserStateChange = null) {
let isErasing = false
// Stylus eraser button - most styluses use button 5 (Samsung S-Pen, Wacom, etc.)
// Some may use button 32, so we check for both
const ERASER_BUTTON_IDS = [5, 32]
// Marker to identify synthetic events and prevent infinite loops
const SYNTHETIC_MARKER = '__eraser_synthetic__'
console.log('[EraserEngine] Initialized. Listening for buttons:', ERASER_BUTTON_IDS)
console.log('[EraserEngine] Canvas element:', canvasElement)
console.log('[EraserEngine] Callback provided:', !!onEraserStateChange)
const handlePointerDown = (e) => {
// Skip synthetic events we created
if (e[SYNTHETIC_MARKER]) {
return
}
// Check if target is canvas
const isCanvasTarget = e.target === canvasElement || canvasElement.contains(e.target)
if (!isCanvasTarget) {
return
}
// Check if this is an eraser button
if (ERASER_BUTTON_IDS.includes(e.button)) {
console.log('[EraserEngine] ✓ ERASER BUTTON', e.button, 'DETECTED! Activating eraser mode')
// STOP the original event from reaching canvas handlers
e.stopPropagation()
e.preventDefault()
isErasing = true
// Notify callback of eraser state change BEFORE dispatching synthetic event
if (onEraserStateChange) {
console.log('[EraserEngine] Calling onEraserStateChange(true)')
onEraserStateChange(true)
}
// Dispatch a synthetic 'pointerdown' event with button 0
const newEvent = new PointerEvent('pointerdown', {
clientX: e.clientX,
clientY: e.clientY,
screenX: e.screenX,
screenY: e.screenY,
pointerId: e.pointerId,
pointerType: e.pointerType,
pressure: e.pressure,
width: e.width,
height: e.height,
tiltX: e.tiltX,
tiltY: e.tiltY,
button: 0,
buttons: 1,
isPrimary: true,
bubbles: true,
cancelable: true
})
newEvent[SYNTHETIC_MARKER] = true
console.log('[EraserEngine] Dispatching synthetic pointerdown to canvas')
canvasElement.dispatchEvent(newEvent)
}
}
const handlePointerMove = (e) => {
// Skip synthetic events we created
if (e[SYNTHETIC_MARKER]) return
if (!isErasing) return
// Stop original event and dispatch synthetic one
e.stopPropagation()
e.preventDefault()
const newEvent = new PointerEvent('pointermove', {
clientX: e.clientX,
clientY: e.clientY,
screenX: e.screenX,
screenY: e.screenY,
pointerId: e.pointerId,
pointerType: e.pointerType,
pressure: e.pressure,
width: e.width,
height: e.height,
tiltX: e.tiltX,
tiltY: e.tiltY,
button: 0,
buttons: 1,
isPrimary: true,
bubbles: true,
cancelable: true
})
newEvent[SYNTHETIC_MARKER] = true
canvasElement.dispatchEvent(newEvent)
}
const handlePointerUp = (e) => {
// Skip synthetic events we created
if (e[SYNTHETIC_MARKER]) {
return
}
if (isErasing) {
console.log('[EraserEngine] Ending eraser mode')
e.stopPropagation()
e.preventDefault()
isErasing = false
// Notify callback of eraser state change
if (onEraserStateChange) {
console.log('[EraserEngine] Calling onEraserStateChange(false)')
onEraserStateChange(false)
}
const newEvent = new PointerEvent('pointerup', {
clientX: e.clientX,
clientY: e.clientY,
screenX: e.screenX,
screenY: e.screenY,
pointerId: e.pointerId,
pointerType: e.pointerType,
pressure: e.pressure,
width: e.width,
height: e.height,
tiltX: e.tiltX,
tiltY: e.tiltY,
button: 0,
buttons: 0,
isPrimary: true,
bubbles: true,
cancelable: true
})
newEvent[SYNTHETIC_MARKER] = true
console.log('[EraserEngine] Dispatching synthetic pointerup')
canvasElement.dispatchEvent(newEvent)
}
}
// Use CAPTURE phase to intercept events BEFORE they reach the canvas
console.log('[EraserEngine] Adding event listeners with capture phase')
window.addEventListener('pointerdown', handlePointerDown, true)
window.addEventListener('pointermove', handlePointerMove, true)
window.addEventListener('pointerup', handlePointerUp, true)
return () => {
console.log('[EraserEngine] Cleanup: removing event listeners')
window.removeEventListener('pointerdown', handlePointerDown, true)
window.removeEventListener('pointermove', handlePointerMove, true)
window.removeEventListener('pointerup', handlePointerUp, true)
}
}
|