HTML5 Canvas と JavaScript を使って作る追尾サンプル 05 – iPhone に対応

phiary に引っ越しました. 毎日プログラミングやWebに関する情報を発信しています! RSS 登録してたまに覗いたり, tweet やハテブして拡散してもらえると幸いです.

Pocket

今回は番外編ということで, iPhone 対応を行います.

SAMPLE

今回制作するサンプルはこちら.

VIDEO

チュートリアルムービー

CODE

今回制作したサンプルの script 部分です.

// 定数
var FPS             = 60;
var SCREEN_WIDTH    = isMobile() ? 320 : 640;
var SCREEN_HEIGHT   = isMobile() ? 460 : 480;
var CIRCLE_RADIUS   = isMobile() ? 20 : 30;
var CIRCLE_MAX_NUM  = isMobile() ? 10 : 15;
var CIRCLE_PURSUIT_RATE = 0.25;  // 収束率

// グローバル
var global = {};
global.context      = null;
global.circleList   = [];
global.touchX       = null;
global.touchY       = null;

window.onload = function()
{
    init();
    run();
};

var init = function()
{
    var canvas = $id("c");
    canvas.width = SCREEN_WIDTH;
    canvas.height= SCREEN_HEIGHT;
    global.context = canvas.getContext("2d");
    
    // Circle を生成
    for (var i=0; i<CIRCLE_MAX_NUM; ++i)
    {
        global.circleList.push(new Circle(
            Math.random() * SCREEN_WIDTH,
            Math.random() * SCREEN_HEIGHT,
            "hsla(" + (360/CIRCLE_MAX_NUM)*i +  ", 75%, 50%, 0.75)"
        ));
    }
    // 1個前に生成された Circle を Target としてセット
    for (var i=1,len=global.circleList.length; i<len; ++i)
    {
        global.circleList&#91;i&#93;.target = global.circleList&#91;i-1&#93;;
    }
    
    // Canvas にマウスイベントを登録
    canvas.addEventListener("mousemove", updateMousePos, false); // マウス移動時イベント
    canvas.addEventListener("mouseout", resetTouchPos, false); // マウスが画面外に出た際のイベント
    
    // Canvas にタッチ時のイベントを登録
    canvas.addEventListener("touchmove", updateTouchPos, false);// タッチ移動時イベント
    canvas.addEventListener("touchend", resetTouchPos, false);  // タッチ終了時イベント
    
    // モバイル対応
    if (isMobile()) {
        $id("header").style.display = "none";
    }
    else {
        document.body.style.margin = "15px";
    }
};

var run = function()
{
    var _run = function()
    {
        update();
        draw();
        
        setTimeout(_run, 1000.0/FPS);
    };
    
    setTimeout(_run, 1000.0/FPS);
};

var update = function()
{
    for (var i=0,len=global.circleList.length; i<len; ++i)
    {
        global.circleList&#91;i&#93;.update();
    }
};

var draw = function()
{
    var ctx = global.context;
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    
    // 円を描画
    ctx.save();
    ctx.globalCompositeOperation = "lighter";
    for (var i=0,len=global.circleList.length; i<len; ++i)
    {
        global.circleList&#91;i&#93;.draw(ctx);
    }
    ctx.restore();
};


/**
 * Circle クラス
 */
var Circle = function(x, y, color)
{
    this.x = x || 0;
    this.y = y || 0;
    this.color = color || "white";
    this.target= null;
};

Circle.prototype = {
    x: null,
    y: null,
    color: null,
    target: null,
    
    update: function()
    {
        if (this.target) {
            this.x += (this.target.x-this.x)*CIRCLE_PURSUIT_RATE;
            this.y += (this.target.y-this.y)*CIRCLE_PURSUIT_RATE;
        }
        else if (global.touchX && global.touchY){
            this.x += (global.touchX-this.x)*CIRCLE_PURSUIT_RATE;
            this.y += (global.touchY-this.y)*CIRCLE_PURSUIT_RATE;
        }
    },
    
    draw: function(ctx)
    {
        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.x, this.y, CIRCLE_RADIUS, 0, Math.PI*2, false);
        ctx.fill();
        ctx.closePath();
    }
};

var updateMousePos = function(e)
{
    var rect = e.target.getBoundingClientRect();
    global.touchX = e.clientX - rect.left;
    global.touchY = e.clientY - rect.top;
};

var updateTouchPos = function(e)
{
    var t = e.touches&#91;0&#93;;
    global.touchX = t.pageX;
    global.touchY = t.pageY;
    e.preventDefault();
};

var resetTouchPos = function()
{
    global.touchX = null;
    global.touchY = null;
};
&#91;/code&#93;</pre>
</section>

<section>
    <h2>TIPS</h2>
    <section>
    <h3>モバイルかを判定</h3>
    <p>
        navigator.userAgent にはブラウザごとに文字列が入っており, それを調べることで環境を調べることができます.
    </p>
    <p>
        今回は, navigator.userAgent に iPhone もしくは Android という文字列が入っていた場合に mobile として判定しています.
    </p>
    <pre class="prettyprint">[code]
// モバイルかを判定
var isMobile = function()
{
    var agent = navigator.userAgent;
    return agent.indexOf("iPhone")>0 || agent.indexOf("Android")>0;
};

iPhone 対応

iPhone 対応についてはこちらで詳しく解説しています.

以上で, HTML5 Canvas と JavaScript を使って作る追尾サンプル は終わりです.

次回は enchant.js で久々に何か作ってみようと思います.

TRACK BACK URL

POST COMMENT

メールアドレスが公開されることはありません。

COMMENT