LoginSignup
3
3

More than 3 years have passed since last update.

AR.jsでインスタストーリーのような操作感を実現する

Last updated at Posted at 2019-10-05

インスタストーリーの操作

ストーリー作成で、テキストサイズや位置を変更したい時、ピンチイン・アウトやドラッグで簡単に操作できる。
最近話題のGoogleの動物たちや、一般的なARアプリも、同じような操作感で3Dモデルを動かすことができる。
これをマーカーベースのAR.jsでも実現したかった。

aframe 0.8.0
ar.js 1.7.7

ソースコード

index.js
function pintch() {
    // イベントリスナー用の透明でフルサイズのレイヤーを準備する。
    let divElement = document.getElementById("target");

    let elScale = {width: 1, height: 1}
    let elPos = {x: 0, y: 0, z: 0}

    let posX = 0;
    let posY = 0;
    let prevPosX = 0;
    let prevPosY = 0;

    // a-obj-model タグをid指定で取得
    let el = document.querySelector("#obj_model");

    // base
    let beseDistance = 0;
    let baseWidth = 0;
    let baseHeight = 0;

    // timeout id
    let timeoutId;

    // touchmoveイベントリスナー
    divElement.addEventListener("touchmove", function(event) {
        event.preventDefault();

        let touches = event.changedTouches;

        if ( touches.length > 1 ) {
            // 二本指で操作しているときの処理(ピンチ)
            let x1 = touches[0].pageX;
            let y1 = touches[0].pageY;

            let x2 = touches[1].pageX;
            let y2 = touches[1].pageY;

            let distance = Math.sqrt( Math.pow( x2-x1, 2 ) + Math.pow( y2-y1, 2 ) );

            clearTimeout( timeoutId );

            if ( beseDistance && baseWidth && baseHeight ) {
                let scale = distance / beseDistance;

                if ( scale && scale != Infinity ) {
                    elScale.width = baseWidth * scale;
                    elScale.height = baseHeight * scale;

                    // a-obj-model の大きさを変更
                    el.setAttribute('scale', {x: elScale.width, y: elScale.height, z: elScale.width});
                }

                timeoutId = setTimeout( function () {
                    beseDistance = 0;
                    baseWidth = 0;
                    baseHeight = 0;
                }, 100 );

            } else {
                console.log('else');
                beseDistance = distance;
                baseWidth = elScale.width;
                baseHeight = elScale.height;
            }
        } else {
            // 一本指で操作しているときの処理(ドラッグ)
            if (posX == 0) {
                prevPosX = touches[0].pageX;
                prevPosY = touches[0].pageY;
                posX = touches[0].pageX;
                posY = touches[0].pageY;
            } else {
                prevPosX = posX;
                prevPosY = posY;
                posX = touches[0].pageX;
                posY = touches[0].pageY;
            }

            let distanceX = posX - prevPosX;
            let distanceY = posY - prevPosY;

            let offset = 30;

            elPos.x = elPos.x + distanceX / offset;
            elPos.y = elPos.y + distanceY / offset;

            // a-obj-model の位置変更
            el.setAttribute('position', {x: elPos.x, y: 0, z: elPos.y});
        }
    });
}

今回使用しているobjのサイズや位置の変更は、以下の部分で行なっている。
マーカーベースなので、位置の変更は2軸だけを考える。

index.js
// a-obj-model タグをid指定で取得
let el = document.querySelector("#obj_model");

// a-obj-model の大きさを変更
// x, y, z共に elScale.width でOKだが、気分的に縦と横だけ区別したかった
el.setAttribute('scale', {x: elScale.width, y: elScale.height, z: elScale.width});

// a-obj-model の位置変更
el.setAttribute('position', {x: elPos.x, y: 0, z: elPos.y});

// 属性指定の値を変更する
// el.setAttribute('属性', {x: x方向の値, y: y方向の値, z: z方向の値});

注意点

これを実装する際、デフォルトのtouchmove イベントリスナーを無効にする必要がある。
こちらの記事を参考にしてください。

AR.jsでスクロールバーが発生する件

参考

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3