JavaScript Move Image

JavaScript の Canvas は基本的にデバイスコンテキストと同じ。
Canvas 上の画像を移動する場合は当然一度塗りつぶして新たな位置に再描写。
コレが基本。

しかし JavaScript は進化していた、レイヤーが使える。
つまりは img タグで指定された画像位置を動的に変更することが可能。

img タグの style に position:absolute を指定。
後はスクリプトで style.top 等の値を代入するだけというお手軽さ。
png 画像の透過属性も適用されたまま移動できる。

以下は半透明なボールのような画像をタッチすると移動できる例。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>画像をタッチして移動する</title>
<!-- for Smart Phone -->
<meta name="viewport" content="
    width=device-width,
    initial-scale=1.0,
    minimum-scale=1.0,
    maximum-scale=1.0,
    user-scalable=no" />
<style>
body {
    margin: 0;
    overflow: hidden;
    -webkit-text-size-adjust: 100%;
}
#ID_CANVAS {
    background-color: #FFEE00;
}
</style>
<script type="text/javascript"><!--

    var canvas = null;
    var context = null;
    var ball = null;
    var offset = 24;

    // Event Handler
    var onBallTouchStart = function(e) {
        e.preventDefault();
    }
    var onBallTouchMove = function(e) {
        context.clearRect(0, 0, canvas.width, canvas.height);
        var touch = e.touches[0];
        var x = touch.pageX;
        var y = touch.pageY;
        context.beginPath();
        context.moveTo(160, 160);
        context.lineTo(x, y);
        context.stroke();
        // Move Layer
        moveBall(x, y);
    }
    var onBallTouchEnd = function(e) {
        context.clearRect(0, 0, canvas.width, canvas.height);
        moveBall(160, 160);
    }
    var moveBall = function(x, y) {
        ball.style.left = x - offset + "px";
        ball.style.top  = y - offset + "px";
    }
    // Connect
    var init = function() {
        if (window.TouchEvent) {
            canvas = document.getElementById("ID_CANVAS");
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight - 100;
            context = canvas.getContext("2d");
            ball = document.getElementById("ID_BALL");
            ball.addEventListener("touchstart",onBallTouchStart);
            ball.addEventListener("touchmove",onBallTouchMove);
            ball.addEventListener("touchend",onBallTouchEnd);
            moveBall(160, 160);
        }
    }
    //-->
</script>

</head>
<body onLoad="init()">
<div>
<canvas id="ID_CANVAS"></canvas>
<img id="ID_BALL" src="ball.png" style="position:absolute">
</div>
<br />
<p><a href=".">Back</a></p>
</body>
</html>

画像をタッチして移動する

touch_move

パソコンとマウスでは JavaScript コンソールで iPhone Emulate で動いた。
まあ実際の端末のようにフリックでのアレはしませんけど。

touch 関連の addEventListener を img タグ位置にしてみた。
この方法なら画像の場所以外でのフリックは iPhone 標準になるね。
アレッと思う場合が減るのでこんな感じにすると良さげ。

透過属性が残ったままなのでラインが透けてみえるのが確認できる。
上手く利用すれば色々な Web アプリに応用できると思う。

注意しないといけないのは画像描写の原点は左上だということ。
上記のような場合は画像サイズの半分をオフセットして描写する。

なんだけど、何故か SO-02D では画像が中心に表示されないのだが。
オフセット無しなら中心に、iPhone 版 Chrome だと中心ってなんだこれ。
Android 全部でそうなのかは解らない、まだ調べること多いな…

追記: Ball を Bool と書いていた部分があったので書き換え、恥ずい…