パンジェンシーの「汗だく開発日誌」

システム開発の備忘録です。

【Javascriptライブラリ】キーイベント発生時に関数を実行する「keyos.js」を作ってみました。

どうも、パンジェンシーでございます。

 

f:id:x-fieldatts:20150502134035p:plain

 

今回も、自分が作成したライブラリの紹介です。

 

Webアプリを作っていると、キーボードでユーザーが何か入力した時に、何かしらの関数を実行するようにしたいということが多々あると思います。

 

しかし、いざ使おうとすると、キーコードを調べたり、テキスト入力フォームにユーザーが入力中にも反応してしまい、フラグを立てるとか、色々面倒くさいです。

 

なので、そこを簡単にやってくれるライブラリ
keyos(キーオス).js」を作成してみました。 ====

 

コード

keyos.js

※2015/8/25
・Enterとテンキーに対応しました。
・some()関数追加。callbackで押されたキー名を取得できるようにしました。

// keyoshita.js
/* example
    var key = keyoshita();
    key.on("keyup","a",function(){
        alert("a oshita!");
    });

    key.on("keypress","↓",function(){
        ("↓");
    });
*/
var keyos = function() {
    var DEBUG = 0;
    var ACCEPT_KEY_INPUT = 1;
    var eventList = ['keyup', 'keypress'];
    var keyCodeList_keyup = {
        13: 'Enter',
        37: '←',
        38: '↑',
        39: '→',
        40: '↓',
        65: 'a',
        66: 'b',
        67: 'c',
        68: 'd',
        69: 'e',
        70: 'f',
        71: 'g',
        72: 'h',
        73: 'i',
        74: 'j',
        75: 'k',
        76: 'l',
        77: 'm',
        78: 'n',
        79: 'o',
        80: 'p',
        81: 'q',
        82: 'r',
        83: 's',
        84: 't',
        85: 'u',
        86: 'v',
        87: 'w',
        88: 'x',
        89: 'y',
        90: 'z',
        48: '0',
        49: '1',
        50: '2',
        51: '3',
        52: '4',
        53: '5',
        54: '6',
        55: '7',
        56: '8',
        57: '9',
        96: '0',
        97: '1',
        98: '2',
        99: '3',
        100: '4',
        101: '5',
        102: '6',
        103: '7',
        104: '8',
        105: '9',
        190: '.',
        188: ',',
    };
    var keyCodeList_keypress = {
        48: '0',
        49: '1',
        50: '2',
        51: '3',
        52: '4',
        53: '5',
        54: '6',
        55: '7',
        56: '8',
        57: '9',
        97: 'a',
        98: 'b',
        99: 'c',
        100: 'd',
        101: 'e',
        102: 'f',
        103: 'g',
        104: 'h',
        105: 'i',
        106: 'j',
        107: 'k',
        108: 'l',
        109: 'm',
        110: 'n',
        111: 'o',
        112: 'p',
        113: 'q',
        114: 'r',
        115: 's',
        116: 't',
        117: 'u',
        118: 'v',
        119: 'w',
        120: 'x',
        121: 'y',
        122: 'z',
        46: '.',
        44: ',',
    };
    var handler = {};
    handler.keyup = {};
    handler.keypress = {};
    var some = {};
    some.keyup = function() {};
    some.keypress = function() {};

    function log(text) {
        if (DEBUG) {
            console.log(text);
        }
    }

    document.getElementsByTagName('body')[0].addEventListener('keyup', function(event) {
        if (ACCEPT_KEY_INPUT) {
            event.preventDefault();
            log("keyup:" + event.keyCode);
            var key = keyCodeList_keyup[event.keyCode];
            if (handler.keyup[key]) {
                log("keyup:" + key);
                handler.keyup[key]();
            } else {
                log("handler is not registered.");
            }
            if (some.keyup) {
                some.keyup(key);
            }
        }
    });

    document.getElementsByTagName('body')[0].addEventListener('keypress', function(event) {
        if (ACCEPT_KEY_INPUT) {
            event.preventDefault();
            log("keypress:" + event.keyCode);
            var key = keyCodeList_keypress[event.keyCode];
            if (handler.keypress[key]) {
                log("keypress:" + key);
                handler.keypress[key]();
            } else {
                log("handler is not registered.");
            }
            if (some.keypress) {
                some.keypress(key);
            }
        }
    });

    return {
        on: function(event, key, callback) {
            if (handler[event]) {
                handler[event][key] = callback;
            } else {
                log('指定されたイベントには対応していません');
            }
        },
        some: function(event, callback) {
            if (some[event]) {
                some[event] = callback;
            } else {
                log('指定されたイベントには対応していません');
            }
        },
        accept: function() {
            ACCEPT_KEY_INPUT = 1;
        },
        refuse: function() {
            ACCEPT_KEY_INPUT = 0;
        }
    };
};


テスト用のページは以下です。
test.html

<!doctype html>
<html lang='ja'>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>keyos test</title>
</head>

<body>
</body>
<script src="keyos.js"></script>
<script>
//**********************************************
// keyos(キーオス).jsは、キーイベントを
// 簡単に扱うためのライブラリです
//**********************************************

var key = keyos();
// まず、keyosオブジェクトを作成します。

key.on("keyup", "e", function() {
  alert("e oshita!");
});
// on()で、キーイベント発生時に実行する
// 関数を登録できます。
// イベントは、"keyup"と"keypress"に
//  対応させています。
// キーは、
// 方向キー,a-z,0-9,".",","に対応しています。
// 他のキーにも対応させたい場合は、ライブラリに
// キーコードを追加してください。

key.on("keypress", "↓", function() {
  console.log("↓");
});

key.on("keyup", "r", function() {
  key.refuse();
  // refuse()をすると、キーイベント発生時に
  // 登録した関数が実行されなくなります
  // accept()をすると、実行される状態に戻ります。
});
</script>

</html>

まとめ

今回は、キーイベントのコールバックを簡単に設定できるライブラリを紹介しました。


誰かのお役に立てれば幸いです。


ではまた。

【Javascriptライブラリ】localStorageを簡単にする「memol.js」を作ってみました。

どうも、パンジェンシーでございます。

 

f:id:x-fieldatts:20150502134035p:plain

 

今回も、自分が作成したライブラリの紹介です。

 

HTML5を使えば、ブラウザ上にリッチなコンテンツを作成することができます。

その中でも、localStorageは、クライアントの端末内にデータを保存できる便利な機能です。

しかし、いざ使おうとすると、色んなアプリで作成したデータがグッチャグッチャになってワケワカメ状態になること必至です。

 

なので、アプリ毎にストレージを分けたり、色々やってくれるライブラリ「memol(メモル).js」を作成してみました。

 

コード

memol.js

// memol.js
/* example
	<script>
	var memo = memol("example");
	memo.set("myname", "xnoudon");
	console.log(memo.get("myname"));
	memo.delAll();
	console.log(memo.get("myname"));
	</script>
*/
var memol = function(storageId) {
    var STORAGE_ID = storageId;
    return {
        'STORAGE_ID': null,
        'get': function(key) {
      // ユーザー情報をオブジェクト形式で取得
            if (window.localStorage && window.localStorage[STORAGE_ID]) {
                var datalist = JSON.parse(
                    window.localStorage.getItem(STORAGE_ID));
                if (datalist[key] !== null) {
                    return datalist[key];
                } else {
                    return null;
                }
            }
            return null;
        },
        'set': function(key, val) {
      // ユーザー情報をローカルストレージに保存
            if (window.localStorage) {
                var datalist;
                if (window.localStorage[STORAGE_ID]) {
                    datalist = JSON.parse(window.localStorage.getItem(STORAGE_ID));
                } else {
                    datalist = {};
                }
                datalist[key] = val;
                window.localStorage.setItem(STORAGE_ID, JSON.stringify(datalist));
                return "set was successful";
            }
            return null;
        },
        'delAll': function() { // 保存したデータを全て削除
            if (window.localStorage) {
                window.localStorage.removeItem(STORAGE_ID);
            }
            return null;
        }
    };
};

テスト用のコードは以下です。

test.html

<!doctype html>
<html lang='ja'>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>memol test</title>
</head>

<body>
  <h2>memol</h2>
  <p>
    <h4>set</h4>
    <input id="input" type="text">
    <button id="set">set</button>
  </p>
  <p>
    <h4>get</h4>
    <button id="get">get</button>
    <textarea id="output"></textarea>
  </p>
  <p>
    <h4>delAll</h4>
    <button id="delAll">delAll</button>
  </p>
</body>
<script src="memol.js"></script>
<script>
//***********************************************
// memol(メモル).jsは、localStorageの読み書きを
// 簡単に行うためのライブラリです
//***********************************************

var memo = memol("example");
// まず、memolオブジェクトを作成します
// 引数として、ストレージの名前を入れます。

document.getElementById("set").addEventListener("click", function() {
  var input = document.getElementById("input").value;

  console.log(memo.set("memo", input));
  // set()は、ストレージにデータを書き込みます。
  // この例では、"example"ストレージに、
  // "memo"という名前で、内容がinputであるデータを書き込みます。

  document.getElementById("input").value = "";
});

document.getElementById("get").addEventListener("click", function() {
  var output = memo.get("memo");
  // get()は、ストレージに書き込んだデータを読み出します。
  // この例では、"example"ストレージに保存してある
  // "memo"という名前のデータの中身を取り出しています。

  document.getElementById("output").innerHTML = output;
});

document.getElementById("delAll").addEventListener("click", function() {
  memo.delAll();
  // dellAll()は、ストレージ内のデータを全て削除します。
  // この例では、"example"ストレージのデータを削除しています。
  // 別の名前で作成したストレージのデータは削除されません。
});
</script>

</html>

まとめ

太古の昔に作成したコードなので、何がどういいのか忘れてしまいましたが、多分、保存するデータが、何でもOKになるところがメリットだと思います。

例えば、連想配列を保存しようとすると、window.localStorage.setItem()では、一旦文字列に変換して保存する必要があり、取り出す際にも、パースする必要があります(多分)。

その辺をライブラリがちゃっちゃとやってくれる感じにしたんだと記憶しています。


誰かのお役に立てれば幸いです。

ではまた。

【Javascriptライブラリ】canvasを使ったアニメーションを作成できる「ugoke.js」を作ってみました。

どうも、パンジェンシーでございます。

 

f:id:x-fieldatts:20150502134035p:plain

 

今回は、自分が作成したライブラリの紹介です。

 

HTML5を使えば、ブラウザ上にリッチなコンテンツを作成することができます。

その中でも、canvasはプログラムだけで様々な画像を作成でき、アニメーションも作成可能ということで注目されています。

 

しかし、アニメーションをするには、タイマーを使って定期的にcanvasをリフレッシュして、また新たに座標をずらした図形を書き込んで…と、少々面倒くさいです。

 

なので、基本的な処理をやってくれるライブラリ「ugoke(ウゴーク).js」を作成してみました。

 

コード

ugoke.js

function ugoke(id) {
    var JOB_INTERVAL = 30;
    var AFTERIMAGE_RATE = 0.9;
    var timerId;
    var canvas, ctx;

    var process = {
        pre: function() {},
        main: function() {},
        post: function() {}
    };

    var bg = {
        r: 0,
        g: 0,
        b: 0
    };

    function job() {
        process.pre(ctx);
        process.main(ctx);
        process.post(ctx);
        timerId = setTimeout(job, JOB_INTERVAL);
    }

    function setBg() {
        var color = "rgb("+bg.r+","+bg.g+","+bg.b+")";
        canvas.style.backgroundColor = color;
    }

    function clearCanvas() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    }

    function afterimageEffect() {
        ctx.save();
        ctx.globalAlpha = 1 - AFTERIMAGE_RATE;
        ctx.fillStyle = "rgb("+bg.r+","+bg.g+","+bg.b+")";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.restore();
    }

    canvas = document.getElementById(id);
    if (!canvas || !canvas.getContext) {
        return false;
    }
    ctx = canvas.getContext("2d");

    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;

    setBg();

    window.onresize = function() {
        canvas.width = canvas.clientWidth;
        canvas.height = canvas.clientHeight;
    };

    return {
        width: function() {
            return canvas.width;
        },
        height: function() {
            return canvas.height;
        },
        bgColor: function(r, g, b) {
            bg.r = r;
            bg.g = g;
            bg.b = b;
            setBg();
        },
        interval: function(interval) {
            JOB_INTERVAL = interval;
        },
        afterimageRate: function(rate) {
            if (0 <= rate && rate <= 1) {
                AFTERIMAGE_RATE = rate;
            }
        },
        preProcess: function(pre) {
            if ("clear" === pre) {
                process.pre = clearCanvas;
            } else if ("afterimage" === pre) {
                process.pre = afterimageEffect;
            }
        },
        mainProcess: function(func) {
            process.main = func;
        },
        run: function() {
            job();
        },
        stop: function() {
            clearTimeout(timerId);
        },
        clear: function() {
            clearCanvas();
        },
        drawText: function(text, x, y, size, color) {
            ctx.save();
            ctx.font = "bold " + size + "px Century Gothic";
            ctx.fillStyle = color;
            ctx.lineJoin = "round";
            ctx.fillText(text, x, y);
            ctx.restore();
        }
    };
}


以上が、作ったライブラリです。


テスト用のHTMLは以下です。


test.html

<!doctype html>
<html lang='ja'>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>ugoke test</title>
</head>

<body>
    <canvas id="ugoke1" width="500" height="500"></canvas>
    <canvas id="ugoke2" width="500" height="500"></canvas>
</body>
<script src="ugoke.js"></script>
<script type="text/javascript">
var x = 0;

//**********************************************************
// ugoke(ウゴーク).jsは、
// canvasで動画を簡単に作成するためのライブラリです。
//**********************************************************
var ugoke1 = ugoke("ugoke1");
// まず、ugokeオブジェクトを作成します。
// この時、canvas要素のidを引数にします。

// ugokeの設定をします。

ugoke1.bgColor(100, 200, 100);
// bgColorは、canvasの背景色の設定です

ugoke1.interval(60);
// intervalは、canvasのフレームレートの設定です

ugoke1.preProcess("clear");
// preProcessは、フレーム毎の前処理を選択します。
// "clear"     : 前フレームの内容を全て削除します
// "afterimage": 前フレームの内容を少し残したままにします(残像効果)
// afterimageを選択した場合、afterimageRate(0〜1)を設定することで残像の具合を調整できます

ugoke1.mainProcess(function(ctx) {
    ctx.save();
    ctx.beginPath();
    ctx.fillStyle = "blue";
    ctx.rect(x, 20, 100, 100);
    ctx.fill();
    ctx.restore();
    if (x < ugoke1.width()) {
        x += 10;
    } else {
        x = 0;
    }
});
// フレーム毎のメインプロセスを設定します
// 引数には関数を設定でき、関数は第一引数として
// canvasのコンテキストオブジェクトをとります
// 図形を描画したりする処理はここに記述します

ugoke1.run();
// run()で、動画をスタートします

// stop()で、動作を一時停止することができます
// clear()で、canvasに書き込んだものをリセットします

var ugoke2 = ugoke("ugoke2");
var y = 0;
ugoke2.bgColor(200, 100, 100);
ugoke2.interval(60);
ugoke2.preProcess("afterimage");
ugoke2.mainProcess(function(ctx) {
    ctx.save();
    ctx.beginPath();
    ctx.fillStyle = "yellow";
    ctx.arc(100, y, 50, 0 * Math.PI / 180, 180 * Math.PI / 180, false);
    ctx.fill();
    ctx.restore();
    if (y < ugoke2.height()) {
        y += 10;
    } else {
        y = 0;
    }
});
ugoke2.run();
</script>

</html>

まとめ

自作のライブラリを紹介しました。

自分が使いやすいように作ったものなので、もしかしたら他の人の役に立たないかもしれませんが…。


ではまた。