update web input handler

This commit is contained in:
Nick Fisher
2025-05-12 10:15:41 +08:00
parent 56e132ec15
commit bb272f2579

View File

@@ -4,7 +4,7 @@ import 'package:web/web.dart' as web;
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
class WebInputHandler { class WebInputHandler {
final DelegateInputHandler inputHandler; final InputHandler inputHandler;
final web.HTMLCanvasElement canvas; final web.HTMLCanvasElement canvas;
late double pixelRatio; late double pixelRatio;
@@ -34,75 +34,76 @@ class WebInputHandler {
void _onMouseDown(web.MouseEvent event) { void _onMouseDown(web.MouseEvent event) {
final localPos = _getLocalPositionFromEvent(event); final localPos = _getLocalPositionFromEvent(event);
final isMiddle = event.button == 1; final button = _getMouseButtonFromEvent(event);
inputHandler.onPointerDown(localPos, isMiddle);
inputHandler.handle(MouseEvent(
MouseEventType.buttonDown,
button,
localPos,
Vector2.zero(),
));
event.preventDefault(); event.preventDefault();
} }
void _onMouseMove(web.MouseEvent event) { void _onMouseMove(web.MouseEvent event) {
final localPos = _getLocalPositionFromEvent(event); final localPos = _getLocalPositionFromEvent(event);
final delta = Vector2(event.movementX ?? 0, event.movementY ?? 0); final delta = Vector2(event.movementX ?? 0, event.movementY ?? 0);
final isMiddle = event.buttons & 4 != 0; final button = _getMouseButtonFromEvent(event);
inputHandler.onPointerMove(localPos, delta, isMiddle);
inputHandler.handle(MouseEvent(
MouseEventType.move,
button,
localPos,
delta,
));
event.preventDefault(); event.preventDefault();
} }
void _onMouseUp(web.MouseEvent event) { void _onMouseUp(web.MouseEvent event) {
final isMiddle = event.button == 1; final localPos = _getLocalPositionFromEvent(event);
inputHandler.onPointerUp(isMiddle); final button = _getMouseButtonFromEvent(event);
inputHandler.handle(MouseEvent(
MouseEventType.buttonUp,
button,
localPos,
Vector2.zero(),
));
event.preventDefault(); event.preventDefault();
} }
void _onMouseWheel(web.WheelEvent event) { void _onMouseWheel(web.WheelEvent event) {
final localPos = _getLocalPositionFromEvent(event); final localPos = _getLocalPositionFromEvent(event);
final delta = event.deltaY; final delta = event.deltaY;
inputHandler.onPointerScroll(localPos, delta);
inputHandler.handle(ScrollEvent(
localPosition: localPos,
delta: delta,
));
event.preventDefault(); event.preventDefault();
} }
void _onKeyDown(web.KeyboardEvent event) { void _onKeyDown(web.KeyboardEvent event) {
PhysicalKey? key; PhysicalKey? key = _getPhysicalKeyFromEvent(event);
switch (event.code) { if (key != null) {
case 'KeyW': inputHandler.handle(KeyEvent(KeyEventType.down, key));
key = PhysicalKey.W;
break;
case 'KeyA':
key = PhysicalKey.A;
break;
case 'KeyS':
key = PhysicalKey.S;
break;
case 'KeyD':
key = PhysicalKey.D;
break;
} }
if (key != null) inputHandler.keyDown(key);
event.preventDefault(); event.preventDefault();
} }
void _onKeyUp(web.KeyboardEvent event) { void _onKeyUp(web.KeyboardEvent event) {
PhysicalKey? key; PhysicalKey? key = _getPhysicalKeyFromEvent(event);
switch (event.code) { if (key != null) {
case 'KeyW': inputHandler.handle(KeyEvent(KeyEventType.up, key));
key = PhysicalKey.W;
break;
case 'KeyA':
key = PhysicalKey.A;
break;
case 'KeyS':
key = PhysicalKey.S;
break;
case 'KeyD':
key = PhysicalKey.D;
break;
} }
if (key != null) inputHandler.keyUp(key);
event.preventDefault(); event.preventDefault();
} }
void _onTouchStart(web.TouchEvent event) { void _onTouchStart(web.TouchEvent event) {
for (var touch in event.changedTouches.toList()) { for (var touch in event.changedTouches.toList()) {
final pos = _getLocalPositionFromTouch(touch); final pos = _getLocalPositionFromTouch(touch);
_touchPositions[touch.identifier] = pos; _touchPositions[touch.identifier] = pos;
@@ -112,10 +113,21 @@ class WebInputHandler {
if (touchCount == 1) { if (touchCount == 1) {
final touch = event.touches.toList().first; final touch = event.touches.toList().first;
final pos = _getLocalPositionFromTouch(touch); final pos = _getLocalPositionFromTouch(touch);
inputHandler.onPointerDown(pos, false); inputHandler.handle(TouchEvent(
TouchEventType.tap,
pos,
null,
));
} }
_handleScaleStart(touchCount, null); if (touchCount >= 2) {
final focalPoint = _calculateFocalPoint(event.touches.toList());
inputHandler.handle(ScaleStartEvent(
numPointers: touchCount,
localFocalPoint: (focalPoint.x, focalPoint.y),
));
}
event.preventDefault(); event.preventDefault();
} }
@@ -126,42 +138,38 @@ class WebInputHandler {
final prevPos = _touchPositions[id]; final prevPos = _touchPositions[id];
if (prevPos != null) { if (prevPos != null) {
final delta = currPos - prevPos; _touchPositions[id] = currPos;
inputHandler.onPointerMove(currPos, delta, false);
} }
_touchPositions[id] = currPos;
} }
final touchCount = event.touches.toList().length; final touchCount = event.touches.toList().length;
if (touchCount >= 2) { if (touchCount >= 2) {
final touches = event.touches.toList().toList(); final touches = event.touches.toList();
final touch0 = touches[0]; final focalPoint = _calculateFocalPoint(touches);
final touch1 = touches[1];
final pos0 = _getLocalPositionFromTouch(touch0); // Calculate scale
final pos1 = _getLocalPositionFromTouch(touch1); final currPositions = touches.map((t) => _getLocalPositionFromTouch(t)).toList();
final prevPos0 = _touchPositions[touch0.identifier]; final prevPositions = touches.map((t) => _touchPositions[t.identifier] ?? _getLocalPositionFromTouch(t)).toList();
final prevPos1 = _touchPositions[touch1.identifier];
final currDist = (currPositions[0] - currPositions[1]).length;
if (prevPos0 != null && prevPos1 != null) { final prevDist = (prevPositions[0] - prevPositions[1]).length;
final prevDist = (prevPos0 - prevPos1).length; final scale = prevDist > 0 ? currDist / prevDist : 1.0;
final currDist = (pos0 - pos1).length;
final scale = currDist / prevDist; // Calculate focal point delta
final focalPoint = (pos0 + pos1) * 0.5; final prevFocalPoint = _calculateFocalPoint(touches, prevPositions);
final focalPointDelta = focalPoint - prevFocalPoint;
inputHandler.onScaleUpdate(
focalPoint, inputHandler.handle(ScaleUpdateEvent(
Vector2(0, 0), numPointers: touchCount,
0.0, localFocalPoint: (focalPoint.x, focalPoint.y),
0.0, localFocalPointDelta: (focalPointDelta.x, focalPointDelta.y),
scale, rotation: 0.0, // We don't track rotation in the web implementation
touchCount, scale: scale,
0.0, horizontalScale: scale,
null, verticalScale: scale,
); ));
}
} }
event.preventDefault(); event.preventDefault();
} }
@@ -171,7 +179,10 @@ class WebInputHandler {
} }
final touchCount = event.touches.toList().length; final touchCount = event.touches.toList().length;
inputHandler.onScaleEnd(touchCount, 0.0); inputHandler.handle(ScaleEndEvent(
numPointers: touchCount,
));
event.preventDefault(); event.preventDefault();
} }
@@ -181,12 +192,37 @@ class WebInputHandler {
} }
final touchCount = event.touches.toList().length; final touchCount = event.touches.toList().length;
inputHandler.onScaleEnd(touchCount, 0.0); inputHandler.handle(ScaleEndEvent(
numPointers: touchCount,
));
event.preventDefault(); event.preventDefault();
} }
void _handleScaleStart(int pointerCount, Duration? sourceTimestamp) { MouseButton? _getMouseButtonFromEvent(web.MouseEvent event) {
inputHandler.onScaleStart(Vector2.zero(), pointerCount, sourceTimestamp); if (event.button == 1 || (event.buttons & 4 != 0)) {
return MouseButton.middle;
} else if (event.button == 0 || (event.buttons & 1 != 0)) {
return MouseButton.left;
} else if (event.button == 2 || (event.buttons & 2 != 0)) {
return MouseButton.right;
}
return null;
}
PhysicalKey? _getPhysicalKeyFromEvent(web.KeyboardEvent event) {
switch (event.code) {
case 'KeyW':
return PhysicalKey.W;
case 'KeyA':
return PhysicalKey.A;
case 'KeyS':
return PhysicalKey.S;
case 'KeyD':
return PhysicalKey.D;
default:
return null;
}
} }
Vector2 _getLocalPositionFromEvent(web.Event event) { Vector2 _getLocalPositionFromEvent(web.Event event) {
@@ -218,6 +254,19 @@ class WebInputHandler {
); );
} }
Vector2 _calculateFocalPoint(List<web.Touch> touches, [List<Vector2>? positions]) {
if (touches.isEmpty) return Vector2.zero();
final points = positions ?? touches.map((t) => _getLocalPositionFromTouch(t)).toList();
Vector2 sum = Vector2.zero();
for (var point in points) {
sum += point;
}
return sum.scaled(1.0 / points.length);
}
void dispose() { void dispose() {
canvas.removeEventListener('mousedown', _onMouseDown.toJS); canvas.removeEventListener('mousedown', _onMouseDown.toJS);
canvas.removeEventListener('mousemove', _onMouseMove.toJS); canvas.removeEventListener('mousemove', _onMouseMove.toJS);
@@ -230,4 +279,4 @@ class WebInputHandler {
canvas.removeEventListener('touchend', _onTouchEnd.toJS); canvas.removeEventListener('touchend', _onTouchEnd.toJS);
canvas.removeEventListener('touchcancel', _onTouchCancel.toJS); canvas.removeEventListener('touchcancel', _onTouchCancel.toJS);
} }
} }