add keyboard support to input
Signed-off-by: Victor Seiji Hariki <victorseijih@gmail.com>
This commit is contained in:
parent
c1bc54a4eb
commit
1d6d2c1978
2 changed files with 151 additions and 20 deletions
117
js/input.js
117
js/input.js
|
@ -2,6 +2,8 @@ const inputConfig = {
|
|||
clickRadius: 10, // Radius to be considered a click (pixels). If farther, turns into a drag
|
||||
clickTiming: 500, // Timing window to be considered a click (ms). If longer, turns into a drag
|
||||
dClickTiming: 500, // Timing window to be considered a double click (ms).
|
||||
|
||||
keyboardHoldTiming: 100, // Timing window after which to consider holding a key (ms)
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -299,5 +301,118 @@ mouse.listen.window.right.onpaintend.on(() =>
|
|||
*/
|
||||
|
||||
/**
|
||||
* Mouse input processing
|
||||
* Keyboard input processing
|
||||
*/
|
||||
// Base object generator functions
|
||||
|
||||
const keyboard = {
|
||||
keys: {},
|
||||
|
||||
isPressed(code) {
|
||||
return this.keys[key].pressed;
|
||||
},
|
||||
|
||||
isHeld(code) {
|
||||
return !!this;
|
||||
},
|
||||
|
||||
shortcuts: {},
|
||||
onShortcut(shortcut, callback) {
|
||||
/**
|
||||
* Adds a shortcut handler (shorcut must be in format: {ctrl?: bool, alt?: bool, shift?: bool, key: string (code)})
|
||||
* key must be the "code" parameter from keydown event; A key is "KeyA" for example
|
||||
*/
|
||||
if (this.shortcuts[shortcut.key] === undefined)
|
||||
this.shortcuts[shortcut.key] = [];
|
||||
|
||||
this.shortcuts[shortcut.key].push({
|
||||
ctrl: shortcut.ctrl,
|
||||
alt: shortcut.alt,
|
||||
shift: shortcut.shift,
|
||||
id: guid(),
|
||||
callback,
|
||||
});
|
||||
},
|
||||
deleteShortcut(id) {
|
||||
this.shortcuts.keys().forEach((key) => {
|
||||
this.shortcuts[key] = this.shortcuts[key].filter((v) => v.id !== id);
|
||||
});
|
||||
},
|
||||
|
||||
listen: {
|
||||
onkeydown: new Observer(),
|
||||
onkeyup: new Observer(),
|
||||
onkeyholdstart: new Observer(),
|
||||
onkeyholdend: new Observer(),
|
||||
onkeyclick: new Observer(),
|
||||
onshortcut: new Observer(),
|
||||
},
|
||||
};
|
||||
|
||||
window.onkeydown = (evn) => {
|
||||
keyboard.listen.onkeydown.emit({
|
||||
code: evn.code,
|
||||
key: evn.key,
|
||||
evn,
|
||||
});
|
||||
|
||||
keyboard.keys[evn.code] = {
|
||||
pressed: true,
|
||||
held: false,
|
||||
_hold_to: setTimeout(() => {
|
||||
keyboard.keys[evn.code].held = true;
|
||||
delete keyboard.keys[evn.code]._hold_to;
|
||||
keyboard.listen.onkeyholdstart.emit({
|
||||
code: evn.code,
|
||||
key: evn.key,
|
||||
evn,
|
||||
});
|
||||
}, inputConfig.keyboardHoldTiming),
|
||||
};
|
||||
|
||||
// Process shortcuts
|
||||
const callbacks = keyboard.shortcuts[evn.code];
|
||||
|
||||
if (callbacks)
|
||||
callbacks.forEach((callback) => {
|
||||
if (
|
||||
!!callback.ctrl === evn.ctrlKey &&
|
||||
!!callback.alt === evn.altKey &&
|
||||
!!callback.shift === evn.shiftKey
|
||||
) {
|
||||
keyboard.listen.onshortcut.emit({
|
||||
code: evn.code,
|
||||
key: evn.key,
|
||||
id: callback.id,
|
||||
evn,
|
||||
});
|
||||
callback.callback(evn);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.onkeyup = (evn) => {
|
||||
keyboard.listen.onkeyup.emit({
|
||||
code: evn.code,
|
||||
key: evn.key,
|
||||
evn,
|
||||
});
|
||||
if (keyboard.keys[evn.code] && keyboard.keys[evn.code].held) {
|
||||
keyboard.listen.onkeyholdend.emit({
|
||||
code: evn.code,
|
||||
key: evn.key,
|
||||
evn,
|
||||
});
|
||||
} else {
|
||||
keyboard.listen.onkeyclick.emit({
|
||||
code: evn.code,
|
||||
key: evn.key,
|
||||
evn,
|
||||
});
|
||||
}
|
||||
|
||||
keyboard.keys[evn.code] = {
|
||||
pressed: false,
|
||||
held: false,
|
||||
};
|
||||
};
|
||||
|
|
54
js/util.js
54
js/util.js
|
@ -2,26 +2,42 @@
|
|||
* Implementation of a simple Oberver Pattern for custom event handling
|
||||
*/
|
||||
function Observer() {
|
||||
this.handlers = new Set();
|
||||
this.handlers = new Set();
|
||||
}
|
||||
|
||||
Observer.prototype = {
|
||||
// Adds handler for this message
|
||||
on(callback) {
|
||||
this.handlers.add(callback);
|
||||
return callback;
|
||||
},
|
||||
clear(callback) {
|
||||
return this.handlers.delete(callback);
|
||||
},
|
||||
emit(msg) {
|
||||
this.handlers.forEach(async (handler) => {
|
||||
try {
|
||||
await handler(msg);
|
||||
} catch (e) {
|
||||
console.warn('Observer failed to run handler');
|
||||
console.warn(handler);
|
||||
}
|
||||
});
|
||||
},
|
||||
// Adds handler for this message
|
||||
on(callback) {
|
||||
this.handlers.add(callback);
|
||||
return callback;
|
||||
},
|
||||
clear(callback) {
|
||||
return this.handlers.delete(callback);
|
||||
},
|
||||
emit(msg) {
|
||||
this.handlers.forEach(async (handler) => {
|
||||
try {
|
||||
await handler(msg);
|
||||
} catch (e) {
|
||||
console.warn("Observer failed to run handler");
|
||||
console.warn(handler);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates unique id
|
||||
*/
|
||||
const guid = (size = 3) => {
|
||||
const s4 = () => {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
};
|
||||
// returns id of format 'aaaaaaaa'-'aaaa'-'aaaa'-'aaaa'-'aaaaaaaaaaaa'
|
||||
let id = "";
|
||||
for (var i = 0; i < size - 1; i++) id += s4() + "-";
|
||||
id += s4();
|
||||
return id;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue