diff --git a/css/apple2.css b/css/apple2.css index 916ef7f..a60881c 100644 --- a/css/apple2.css +++ b/css/apple2.css @@ -217,6 +217,8 @@ canvas { image-rendering: optimizeSpeed; width: 592px; height: 416px; + touch-action: manipulation; + user-select: none; } #screen.mouseMode { diff --git a/index.html b/index.html index 37fa90a..cf1a2aa 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,9 @@ PreApple II + + + diff --git a/js/ui/mouse.ts b/js/ui/mouse.ts index c16b255..fdcc3ef 100644 --- a/js/ui/mouse.ts +++ b/js/ui/mouse.ts @@ -1,30 +1,87 @@ import type Mouse from '../cards/mouse'; import { enableMouseMode } from './joystick'; +type TouchEventWithTarget = TouchEvent & { target: HTMLCanvasElement }; + export class MouseUI { private mouse: Mouse; constructor(private canvas: HTMLCanvasElement) { - this.canvas.addEventListener( - 'mousemove', - (event: MouseEvent & { target: HTMLCanvasElement} ) => { - const { offsetX, offsetY, target } = event; - this.mouse.setMouseXY( - offsetX, - offsetY, - target.clientWidth, - target.clientHeight - ); + const updateTouchXY = (event: TouchEventWithTarget) => { + const { targetTouches, target } = event; + if (targetTouches.length < 1) { + return; } - ); + const rect = target.getBoundingClientRect(); + const leftPad = (rect.width - 560) / 2 + rect.left; + const topPad = (rect.height - 384) / 2 + rect.top; + const { clientX, clientY } = targetTouches[0]; + const xPos = clientX - leftPad; + const yPos = clientY - topPad; + this.mouse.setMouseXY( + Math.max(Math.min(xPos, 559), 0), + Math.max(Math.min(yPos, 383), 0), + 560, + 384, + ); + }; - this.canvas.addEventListener('mousedown', () => { - this.mouse.setMouseDown(true); - }); + if ('ontouchstart' in window) { + this.canvas.addEventListener( + 'touchmove', + (event: TouchEventWithTarget) => { + updateTouchXY(event); + } + ); - this.canvas.addEventListener('mouseup', () => { - this.mouse.setMouseDown(false); - }); + this.canvas.addEventListener( + 'touchstart', + (event: TouchEventWithTarget) => { + updateTouchXY(event); + // Make sure the mouse down is processed in a different + // pass as the move, so that a simple tap isn't treated like + // a drag. + setTimeout(() => this.mouse.setMouseDown(true), 100); + } + ); + + this.canvas.addEventListener( + 'touchend', + (event: TouchEventWithTarget) => { + updateTouchXY(event); + this.mouse.setMouseDown(false); + } + ); + + this.canvas.addEventListener( + 'touchcancel', + (event: TouchEventWithTarget) => { + updateTouchXY(event); + this.mouse.setMouseDown(false); + } + ); + } else { + this.canvas.addEventListener( + 'mousemove', + (event: MouseEvent & { target: HTMLCanvasElement} ) => { + const { offsetX, offsetY, target } = event; + this.mouse.setMouseXY( + offsetX, + offsetY, + target.clientWidth, + target.clientHeight + ); + } + ); + + this.canvas.addEventListener('mousedown', () => { + this.mouse.setMouseDown(true); + }); + + this.canvas.addEventListener('mouseup', () => { + this.mouse.setMouseDown(false); + }); + } } setMouse = (mouse: Mouse) => {