const specialKeyMap = { 'backspace': 8, 'tab': 9, 'enter': 13, 'shift': 16, 'ctrl': 17, 'alt': 18, 'pausebreak': 19, 'capslock': 20, 'escape': 27, 'pgup': 33, 'pgdown': 34, 'end': 35, 'home': 36, 'left': 37, 'up': 38, 'right': 39, 'down': 40, 'insert': 45, 'delete': 46, 'left-window': 91, 'right-window': 92, 'select': 93, 'numpad0': 96, 'numpad1': 97, 'numpad2': 98, 'numpad3': 99, 'numpad4': 100, 'numpad5': 101, 'numpad6': 102, 'numpad7': 103, 'numpad8': 104, 'numpad9': 105, 'multiply': 106, 'add': 107, 'subtract': 109, 'decimal': 110, 'divide': 111, 'f1': 112, 'f2': 113, 'f3': 114, 'f4': 115, 'f5': 116, 'f6': 117, 'f7': 118, 'f8': 119, 'f9': 120, 'f10': 121, 'f11': 122, 'f12': 123, 'numlock': 144, 'scrolllock': 145, 'semi-colon': 186, 'equals': 187, 'comma': 188, 'dash': 189, 'period': 190, 'fwdslash': 191, 'grave': 192, 'open-bracket': 219, 'bkslash': 220, 'close-braket': 221, 'single-quote': 222 } class Input { constructor (canvas) { this.keyList = {} this.previousKeyList = {} this.canvas = canvas this.mouse = { pos: { x: 0, y: 0 }, frame: { x: 0, y: 0 }, previous: { x: 0, y: 0 } } window.addEventListener('keydown', (e) => this.keyDown(e), false) window.addEventListener('keyup', (e) => this.keyUp(e), false) canvas.addEventListener('mousemove', (e) => { let x let y if (e.changedTouches) { let touch = e.changedTouches[0] if (touch) { e.pageX = touch.pageX e.pageY = touch.pageY } } if (e.pageX || e.pageY) { x = e.pageX y = e.pageY } else { x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop } x -= canvas.offsetLeft y -= canvas.offsetTop this.mouse.frame.x = x this.mouse.frame.y = y }, false) canvas.addEventListener('mousedown', (e) => { e.preventDefault() this.mouse['btn' + e.button] = true }) canvas.addEventListener('mouseup', (e) => { e.preventDefault() this.mouse['btn' + e.button] = false }) canvas.addEventListener('contextmenu', (e) => { e.preventDefault() }) } get mousePos () { return this.mouse.pos } get mouseMoved () { return (this.mouse.pos.x !== this.mouse.previous.x || this.mouse.pos.y !== this.mouse.previous.y) } get mouseOffset () { return { x: this.mouse.previous.x - this.mouse.pos.x, y: this.mouse.previous.y - this.mouse.pos.y } } toggleKey (keyCode, on) { // Find key in special key list let key = null for (let k in specialKeyMap) { let val = specialKeyMap[k] if (keyCode === val) { key = k break } } // Use fromCharCode if (!key) { key = String.fromCharCode(keyCode).toLowerCase() } this.keyList[key] = (on === true) } keyDown (e) { let keycode if (window.event) { keycode = window.event.keyCode } else if (e) { keycode = e.which } this.toggleKey(keycode, true) } keyUp (e) { let keycode if (window.event) { keycode = window.event.keyCode } else if (e) { keycode = e.which } this.toggleKey(keycode, false) } down (key) { return this.keyList[key] != null ? this.keyList[key] : false } downLast (key) { return this.previousKeyList[key] != null ? this.previousKeyList[key] : false } isDown (key) { return this.down(key) && this.downLast(key) } isUp (key) { return !this.isDown(key) } isPressed (key) { return this.down(key) === true && this.downLast(key) === false } update () { this.previousKeyList = {} for (let k in this.keyList) { if (this.keyList[k] === true) { this.previousKeyList[k] = true } } // Mouse positions in the previous frame this.mouse.previous.x = this.mouse.pos.x this.mouse.previous.y = this.mouse.pos.y // Mouse positions in the current frame // Convert to OpenGL coordinate system this.mouse.pos.x = this.mouse.frame.x / this.canvas.width * 2 - 1 this.mouse.pos.y = this.mouse.frame.y / this.canvas.height * 2 - 1 } } export default Input