Better mouse event handling (#552)
* Use learnings from touch events in Blockly and apply to the Ev3 sim. Register move and up events on the document rather than the individual element allowing users greater flexibility where they move their mouse once it's down. * Add mouse leave events
This commit is contained in:
parent
6e1a613798
commit
b69af383a6
@ -93,9 +93,6 @@ namespace pxsim.visuals {
|
|||||||
}, () => {
|
}, () => {
|
||||||
captured = false;
|
captured = false;
|
||||||
rect.setAttribute('cursor', '-webkit-grab');
|
rect.setAttribute('cursor', '-webkit-grab');
|
||||||
}, () => {
|
|
||||||
captured = false;
|
|
||||||
rect.setAttribute('cursor', '-webkit-grab');
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.group;
|
return this.group;
|
||||||
|
@ -67,9 +67,6 @@ namespace pxsim.visuals {
|
|||||||
}, () => {
|
}, () => {
|
||||||
captured = false;
|
captured = false;
|
||||||
dragSurface.setAttribute('cursor', '-webkit-grab');
|
dragSurface.setAttribute('cursor', '-webkit-grab');
|
||||||
}, () => {
|
|
||||||
captured = false;
|
|
||||||
dragSurface.setAttribute('cursor', '-webkit-grab');
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.group;
|
return this.group;
|
||||||
|
@ -66,9 +66,6 @@ namespace pxsim.visuals {
|
|||||||
}, () => {
|
}, () => {
|
||||||
captured = false;
|
captured = false;
|
||||||
this.handleSliderUp();
|
this.handleSliderUp();
|
||||||
}, () => {
|
|
||||||
captured = false;
|
|
||||||
this.handleSliderUp();
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.group;
|
return this.group;
|
||||||
|
@ -66,9 +66,6 @@ namespace pxsim.visuals {
|
|||||||
}, () => {
|
}, () => {
|
||||||
captured = false;
|
captured = false;
|
||||||
dragSurface.setAttribute('cursor', '-webkit-grab');
|
dragSurface.setAttribute('cursor', '-webkit-grab');
|
||||||
}, () => {
|
|
||||||
captured = false;
|
|
||||||
dragSurface.setAttribute('cursor', '-webkit-grab');
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.group;
|
return this.group;
|
||||||
|
@ -47,8 +47,6 @@ namespace pxsim.visuals {
|
|||||||
}
|
}
|
||||||
}, () => {
|
}, () => {
|
||||||
captured = false;
|
captured = false;
|
||||||
}, () => {
|
|
||||||
captured = false;
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.group;
|
return this.group;
|
||||||
|
@ -10,33 +10,85 @@ namespace pxsim.visuals {
|
|||||||
|
|
||||||
export type TouchCallback = (event: MouseEvent | TouchEvent | PointerEvent) => void;
|
export type TouchCallback = (event: MouseEvent | TouchEvent | PointerEvent) => void;
|
||||||
|
|
||||||
export function touchEvents(e: SVGElement | SVGElement[], move?: TouchCallback, down?: TouchCallback, up?: TouchCallback, leave?: TouchCallback) {
|
export function touchEvents(e: SVGElement | SVGElement[], move?: TouchCallback, down?: TouchCallback, up?: TouchCallback) {
|
||||||
if (Array.isArray(e)) {
|
if (Array.isArray(e)) {
|
||||||
e.forEach(el => bindEvents(el, move, down, up, leave));
|
e.forEach(el => bindEvents(el, move, down, up));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bindEvents(e, move, down, up, leave);
|
bindEvents(e, move, down, up);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindEvents(e: SVGElement, move?: TouchCallback, down?: TouchCallback, up?: TouchCallback, leave?: TouchCallback) {
|
function bindEvents(e: SVGElement, move?: TouchCallback, down?: TouchCallback, up?: TouchCallback) {
|
||||||
if ((window as any).PointerEvent) {
|
|
||||||
if (down) e.addEventListener("pointerdown", down);
|
const moveEvent = move ? (ev: MouseEvent) => {
|
||||||
if (up) e.addEventListener("pointerup", up);
|
move.call(this, ev);
|
||||||
if (leave) e.addEventListener("pointerleave", leave);
|
ev.preventDefault();
|
||||||
if (move) e.addEventListener("pointermove", move);
|
ev.stopPropagation();
|
||||||
|
} : undefined;
|
||||||
|
|
||||||
|
const enterEvent = move ? (ev: MouseEvent) => {
|
||||||
|
if (ev.buttons != 1) {
|
||||||
|
// cancel all events when we re-enter without a button down
|
||||||
|
upEvent(ev);
|
||||||
}
|
}
|
||||||
else {
|
} : undefined;
|
||||||
if (down) e.addEventListener("mousedown", down);
|
|
||||||
if (up) e.addEventListener("mouseup", up);
|
const upEvent = up ? (ev: MouseEvent) => {
|
||||||
if (leave) e.addEventListener("mouseleave", leave);
|
up.call(this, ev);
|
||||||
if (move) e.addEventListener("mousemove", move);
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
// Unregister document up and move events
|
||||||
|
if ((window as any).PointerEvent) {
|
||||||
|
if (moveEvent) document.removeEventListener("pointermove", moveEvent);
|
||||||
|
if (upEvent) document.removeEventListener("pointerup", upEvent);
|
||||||
|
if (upEvent) document.removeEventListener("pointercancel", upEvent);
|
||||||
|
if (moveEvent) document.removeEventListener("pointerenter", enterEvent);
|
||||||
|
} else {
|
||||||
|
if (moveEvent) document.removeEventListener("mousemove", moveEvent);
|
||||||
|
if (upEvent) document.removeEventListener("mouseup", upEvent);
|
||||||
|
if (moveEvent) document.removeEventListener("mouseenter", enterEvent);
|
||||||
|
if (pxsim.svg.isTouchEnabled()) {
|
||||||
|
if (moveEvent) document.removeEventListener("touchmove", moveEvent);
|
||||||
|
if (upEvent) document.removeEventListener("touchend", upEvent);
|
||||||
|
if (upEvent) document.removeEventListener("touchcancel", upEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} : undefined;
|
||||||
|
|
||||||
|
const downEvent = down ? (ev: MouseEvent) => {
|
||||||
|
down.call(this, ev);
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
// Register document up and move events
|
||||||
|
if ((window as any).PointerEvent) {
|
||||||
|
if (moveEvent) document.addEventListener("pointermove", moveEvent);
|
||||||
|
if (upEvent) document.addEventListener("pointerup", upEvent);
|
||||||
|
if (upEvent) document.addEventListener("pointercancel", upEvent);
|
||||||
|
if (moveEvent) document.addEventListener("pointerenter", enterEvent);
|
||||||
|
} else {
|
||||||
|
if (moveEvent) document.addEventListener("mousemove", moveEvent);
|
||||||
|
if (upEvent) document.addEventListener("mouseup", upEvent);
|
||||||
|
if (moveEvent) document.addEventListener("mouseenter", enterEvent);
|
||||||
|
|
||||||
if (pxsim.svg.isTouchEnabled()) {
|
if (pxsim.svg.isTouchEnabled()) {
|
||||||
if (down) e.addEventListener("touchstart", down);
|
if (moveEvent) document.addEventListener("touchmove", moveEvent);
|
||||||
if (up) e.addEventListener("touchend", up);
|
if (upEvent) document.addEventListener("touchend", upEvent);
|
||||||
if (leave) e.addEventListener("touchcancel", leave);
|
if (upEvent) document.addEventListener("touchcancel", upEvent);
|
||||||
if (move) e.addEventListener("touchmove", move);
|
}
|
||||||
|
}
|
||||||
|
} : undefined;
|
||||||
|
|
||||||
|
if ((window as any).PointerEvent) {
|
||||||
|
if (downEvent) e.addEventListener("pointerdown", downEvent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (downEvent) e.addEventListener("mousedown", downEvent);
|
||||||
|
|
||||||
|
if (pxsim.svg.isTouchEnabled()) {
|
||||||
|
if (downEvent) e.addEventListener("touchstart", downEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user