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

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

【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>

まとめ

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

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


ではまた。

【Ubuntu】【Node.js】SSL対応ウェブアプリ(テスト目的)を作ってみた

こんにちわ!
パンジェンシーです。

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

 

今回は、SSL対応の方法です。

と言っても、ちゃんとお金を払って作ってもらう証明書でなく、テスト用のオレオレ証明書を使った方法です。

環境

 

OpenSSLのインストール

まず、UbuntuにOpenSSLをインストールします。

$ sudo apt-get install openssl

サーバー証明書の作成

まず、作業用のディレクトリーを作成しましょう。

$ mkdir ssl-cert
$ cd ssl-cert


次に、秘密鍵を作成します。

$ openssl genrsa -des3 -out server.key 1024

パスフレーズを聞かれるので、入力します。

これで、server.keyが作成されます。


次に、証明書署名要求(csr)を作成します。

$ openssl req -new -key server.key -out server.csr

server.keyを作成した時に入力したパスフレーズを聞かれるので入力します。

他にも色々聞かれますが、「Common Name」の部分は、アプリのIPアドレスを入力しましょう。

ここをちゃんと入力しなかった場合、クライアントのブラウザに証明書をインストールしても、「この証明書はあんたのもんじゃないよ!」とかで怒られて警告が消えません。

特にそれでも問題なければ適当に入力しても構いません。

これで、server.csrが作成されます。


次に、サーバー証明書を作成します。

$ openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt

また、server.keyのパスフレーズを聞かれるので入力します。

これでserver.crtが作成されます。

アプリのSSL対応

Expressのバージョンによってもやり方が違うみたいですが、今回は4.x系でのやり方です。

まず、先ほど作成した証明書をディレクトリーごとプロジェクトにコピーします。

ここでは、

pangency.hatenablog.com

で作成したサンプルアプリに修正を加えます。


bin/wwwを以下のように書き直します。

bin/www

#!/usr/bin/env node
var debug = require('debug')('sample-login');
var app = require('../app');
var fs = require('fs');
var https = require('https');

var options = {
    //passphrase: [ここにパスフレーズを入力]
    key: fs.readFileSync('./ssl-cert/server.key'),
    cert: fs.readFileSync('./ssl-cert/server.crt')
};

app.set('port', process.env.PORT || 3000);

var server = https.createServer(options, app).listen(app.get('port'), function() {
    debug('Express server listening on port ' + server.address().port);
});

実行

では、アプリを実行してみましょう。

$ npm start

パスフレーズを聞かれるので入力するとアプリが起動します(上記コードのoptions内でコメントアウトしているpassphraseの部分にパスフレーズを入力しておけば、ここでいちいち入力しなくていいのですが、パスフレーズが平文でコードに埋め込まれているのはセキュリティ上アカンと思います。今回はテスト用なのでそれでもいいかな?)。


ブラウザから、https://127.0.0.1:3000にアクセスします。

アプリの画面が表示されれば成功です!

まとめ

今回は、オレオレ証明書を使ったSSL対応をしました。

テスト用としてはこれでよいと思いますが、決してこのまま外部に出さないようにしましょう…。


以上

【MongoDB】基本的なコマンドの使い方

こんにちわ!
パンジェンシーです。

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

 

今回は、MongoDBの基本的な使い方の備忘録を書いておきます。

用語の定義

フィールド フィールド名と値のセットです。フィールドリレーショナル・データベースのカラムに相当。
ドキュメント 複数のフィールドの集まりです。リレーショナル・データベースのレコードに相当。
コレクション ドキュメントの集まりです。リレーショナル・データベースのテーブルに相当。
データベース(db) コレクションの集まりです。リレーショナル・データベースのデータベースと同じ意味です。
db
 L collection
    L document{{field:value},{field:value},{field:value}}
    L document{{field:value},{field:value},{field:value}}
    L document{{field:value},{field:value},{field:value}}
 L collection
    L document{{field:value},{field:value},{field:value}}
    L document{{field:value},{field:value},{field:value}}
    L document{{field:value},{field:value},{field:value}}

という感じのイメージみたいです。

 

データベースへのアクセス

MongoDBにアクセスするには、端末からmongoと入力します。

$ mongo

すると、mongoシェルが立ち上がります。


バージョンを表示してみましょう。

> version()
2.4.9


データベースの一覧を見る場合には、

> show dbs

とします。

データベースにアクセスするには、

> use [db名]

とします。


更に、dbに含まれるコレクションを参照したい場合は、

> show collections

とします。

ドキュメントを追加する方法

データベースに新しいドキュメントを追加するには、insert()を使います。

ここでは、データベース名をdb1、コレクション名をcol1とし、

{
    name: "takashi",
    age: 18
}

というドキュメントを追加したいとします。

> use db1
> db.col1.insert({ name: "takashi", age: 18 })

で追加できます。

find()で内容を確認してみましょう。

> db.col1.find()

フィールドの値を変更する方法

既に入力したドキュメントのフィールドの値を変更する場合は、update()を使います。

takashiの年齢を19歳に変更する場合、

> db.col1.update({ name: "takashi"}, { $set: { age: 19 } })

とします。

第一引数{ name: "takashi"}をクエリといい、コレクションの中からnameがtakashiのドキュメントを探してきます。

第二引数はオペレーションといい、$setオペレーターだと、ageの値を19に置き換えます。

他の主なオペレーターの意味は以下です。

$inc 数値を足したり引いたりできます
$mul 数値をかけます
$rename フィールド名を変更します
$unset フィールドを削除します


フィールドの値がArray(配列)の場合は、

$push 配列に要素を追加
$pull 配列から要素を削除
$pop 配列から要素を1つ取り出す

などができます。

オペレーターは他にも色々あります。

ドキュメントを削除する方法

既に入力したドキュメントを削除する場合は、remove()を使います。

nameがtakashiのドキュメントを削除したい場合は、

> db.col1.remove({ name: "takashi" })

とします。

ドキュメントを検索する方法

コレクションの中から、特定のドキュメントを検索する場合は、find()を使います。

コレクションの中から、ageが18のドキュメントのnameフィールドを抽出したい場合は、こう書きます。

> db.col1.find( { age: 18 }, { name: 1, _id: 0 })

第一引数はクエリ、第二引数には、抽出したいフィールドを1,抽出しないフィールドを0で指定します。

_idというのは、ドキュメントを追加した時に自動で割り振られるIDです。

第二引数を指定した場合、_idと1に指定したフィールドが抽出されます。

_idを抽出したくない場合は、0を指定する必要があります。

まとめ

他にも色々なことができますが、わたくしが使っているのはだいたいこんなものです。


以上