読み書きプログラミング

日常のプログラミングで気づいたことを綴っています

ウェブで、iOS7のような動く壁紙を作る

iOS7では壁紙にパノラマ写真を選ぶと壁紙が動くそうです。
面白い。でも、ウェブで簡単にできますね。やってみましょう。
端末の姿勢(オイラー角)を扱うのに、Three.jsを使いました。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Wall paper</title>
    <style type="text/css">
html, body {
    height: 100%;
}
body {
    background-image: url('panorama.jpg'); /* 縦長もしくは横長の画像を用意 */
    background-position: 50% 50%;
    background-size: cover; /* もし縦横とも大きな写真を使いたかったら、縦横サイズをpxで指定 */
    background-repeat: no-repeat;
}
    </style>
</head>
<body>
    <script src="//cdnjs.cloudflare.com/ajax/libs/three.js/r58/three.min.js"></script>
    <script src="wallpaper.js"></script> <!-- wallpaper.jsはwallpaper.coffeeをコンパイルしたもの -->
</body>
</html>
matrix0 = null #最初の端末の姿勢を基準にするための回転逆行列

window.addEventListener 'deviceorientation', (event) ->
    if matrix0 is null
        matrix0 = 'ready' # deviceorientationの初回の値は信用できないので、捨てる。
        return
    else if matrix0 is 'ready'
        matrix0 = new THREE.Matrix4()
        matrix0.makeRotationFromEuler new THREE.Vector3(event.beta / 360 * 2 * Math.PI, event.gamma / 360 * 2 * Math.PI, event.alpha / 360 * 2 * Math.PI), 'ZXY'
        # 'ZXY'はdeviceorientation eventの定義
        matrix0.getInverse matrix0

    matrix = new THREE.Matrix4()
    matrix.makeRotationFromEuler new THREE.Vector3(event.beta / 360 * 2 * Math.PI, event.gamma / 360 * 2 * Math.PI, event.alpha / 360 * 2 * Math.PI), 'ZXY'
    matrix.multiply matrix0 #最初の姿勢の逆行列を掛けて最初の姿勢からの回転行列を得る。
    relative = new THREE.Vector3().setEulerFromRotationMatrix matrix, 'XYZ'
    # 端末の姿勢の変化を考慮する際に、X軸Y軸を優先するために、’XYZ’を指定する。
    document.body.style.backgroundPositionX = - relative.y / Math.PI * 100 + 50 + '%'
    document.body.style.backgroundPositionY = - relative.x / (2 * Math.PI) * 100 + 50 + '%'