Keeb's Quest - 004 A little visual keyboard test

An element I think I need for the finished game.
Created: 2019-11-17
colorful keeb’s quest logo

Taking a pause from the main idea for a moment (but in no way deterred), I decided to tackle something else I thought I’d need for the finished game: an on-screen keyboard for visual feedback (and highlighting new keys as the player earns them and that sort of thing).

This was written in mithril.js, which is a tiny framework that features virtual DOM rendering, etc. (My old Dave’s Guide to Mithril may be somewhat out of date, but is still mostly relevant. I swear an update is coming someday.)

The keyboard is rendered with <div> tags styled with rounded borders in CSS. The keys you press on your real keyboard flash and fade out on the on-screen keyboard. The entire application (HTML, JS, and CSS) comes to a grand total of just 82 lines!

Check out how I’m storing the keyboard with the sizes of the keys encoded (125 is a 1.25 unit keycap):

var keyboard_layout = [
    [' ','1','2','3','4','5','6','7','8','9','0','-','=','Backspace/200'],
    ['Tab/150','q','w','e','r','t','y','u','i','o','p','[',']','\\/150'],
    ['Caps/175','a','s','d','f','g','h','j','k','l',';',' ','Enter/225'],
    ['Shift/225','z','x','c','v','b','n','m',',','.','slash','Shift/275'],
    ['Ctrl/125',' /125','Alt/125',' /625','Alt/125',' /125',' /125','Ctrl/125'],
].map(function(row){

The flash and fade are handled by toggling a CSS class with a CSS animation.

Here’s the entire contents of view() (the rendering function) for the keyboard:

    return keyboard_layout.map(function(row){
        return m(".row", row.map(function(key){
            var flash='';
            if(key.label===key_pressed){
                flash = '.flash';
            }
            return m('.key'+key.width+flash, m.trust(key.label));
        }));
    });

Here’s the result:

screenshot of the on-screen keyboard demo

Click on the screenshot above or this link to try it out: 004/keyboard_test.html

I get a real kick out of how little code I needed to get this to work. It was an absolute blast to write.

(I think it also shows how delightful "immediate-mode" virtual DOM rendering of application state can be versus traditional DOM manipulation!)