LoginSignup
2
2

More than 3 years have passed since last update.

WebARのアニメーション

Last updated at Posted at 2020-04-25

やること

ARで立方体のオブジェクトを表示して、
その立方体オブジェクトをクリック(orタッチ)すると回転する

Three.jsのrotationを使った回転と
Tween.jsを使った回転のサンプルスクリプト

ソース

githubに格納 -> ClickToMove

ブラウザがカメラにアクセスするため ↓ などでSSL(https)対応Webサーバを用意

ARマーカ hiro はネットで別途調達が必要

動作確認結果

以下の条件で動作を確認

  • Win10 Chrome (バージョン 81.0.4044.122)
  • Win10 FireFox (バージョン 75.0)
  • Win10 Microsoft Edge
  • iOS13 Safari
  • Android9 Chrome

※スマホ(iOS,Android)では、画面タッチしても立方体が動かずに何回も画面タッチした。

スクリプトの説明

image.png

mesh01の立方体を作るスクリプトはここ

//-- ↓ 立方体1つ目 ↓ ---------------------------------//
let geometry01  = new THREE.CubeGeometry(1,1,1);
let material01 = [
    new THREE.MeshLambertMaterial({color: 0xE9546B,opacity: 0.3,transparent: true,side: THREE.DoubleSide}), // right
    new THREE.MeshLambertMaterial({color: 0xE9546B,opacity: 0.4,transparent: true,side: THREE.DoubleSide}), // left
    new THREE.MeshLambertMaterial({color: 0x00A95F,opacity: 0.5,transparent: true,side: THREE.DoubleSide}), // front
    new THREE.MeshLambertMaterial({color: 0x00A95F,opacity: 0.6,transparent: true,side: THREE.DoubleSide}), // back
    new THREE.MeshLambertMaterial({color: 0x187FC4,opacity: 0.7,transparent: true,side: THREE.DoubleSide}), // top
    new THREE.MeshLambertMaterial({color: 0x187FC4,opacity: 0.8,transparent: true,side: THREE.DoubleSide}), // bottom
];
mesh01 = new THREE.Mesh( geometry01, material01 );
mesh01.position.y = 0.5;
mesh01.name = "OBJECT001";
markerRoot01.add( mesh01 );
//-- ↑ 立方体1つ目 ↑ ---------------------------------//

クリック(orタップ)自の処理はここ、これもどこかのソースをコピーさせたもらった(どこだっけ・・)

//===================================================================
// マウスダウン(タップ)によるピッキング処理
//===================================================================
window.addEventListener("mousedown", function(ret) {
  let mouseX = ret.clientX;                           // マウスのx座標
  let mouseY = ret.clientY;                           // マウスのy座標
  //console.log(mouseX + " : " + mouseY);
  mouseX =  (mouseX / window.innerWidth)  * 2 - 1;    // -1 ~ +1 に正規化されたx座標
  mouseY = -(mouseY / window.innerHeight) * 2 + 1;    // -1 ~ +1 に正規化されたy座標
  let pos = new THREE.Vector3(mouseX, mouseY, 1);     // マウスベクトル
  pos.unproject(camera);                              // スクリーン座標系をカメラ座標系に変換
  // レイキャスタを作成(始点, 向きのベクトル)
  let ray = new THREE.Raycaster(camera.position, pos.sub(camera.position).normalize());
  let obj = ray.intersectObjects(scene.children, true);   // レイと交差したオブジェクトの取得
  if(obj.length > 0) {                                // 交差したオブジェクトがあれば
    picked(obj[0].object.name);                       // ピックされた対象に応じた処理を実行
    console.log("debug 001");
  }
  console.log("-----");
});

クリック(orタップ)したところにオブジェクトがあれば、各オブジェクトに用意したフラグが変わる

mesh01, mesh02の立方体は、フラグ(m01Flg,m02Flg)が1以外のときに、Three.jsのrotationで回転する。

function animate()
{
    requestAnimationFrame(animate);
    deltaTime = clock.getDelta();
    update();
    render();
}

function update()
{
    if( arToolkitSource.ready !== false ) arToolkitContext.update( arToolkitSource.domElement );
    if( m01Flg != 1){
        mesh01.rotation.x += 0.1
    }
    if( m02Flg != 1){
        mesh02.rotation.y += 0.1
    }
}

mesh03の立方体は、フラグ(m03Flg)が0以外のときに、Three.jsのrotationで回転する。(ソースは こちらから拝借 )

//===================================================================
// TWEEN
//===================================================================
let cube_size = 1; // cubeのサイズ
let cube_count = 1; // cubeの配置数
let grid_count = 10; // グリッドの分割数
let interval = 1000; // 移動アニメーションの間隔
let duration = 500; // 1回の移動時間
let stop_rate = 0; // 移動しない確率
let cube_half = cube_size / 2;

TWEEN.autoPlay(true);
let next_move = function () {
    if(m03Flg != 0){
        let origin_pos = mesh03.position.clone();
        let origin_quaternion = mesh03.quaternion.clone();
        let move_axis = 'x';
        let move_offset = cube_size;
        let from_param = { x: 0 }; // tween開始時の値
        let to_param   = { x: 1 }; // tween終了時の値
        let duration = 500; // 単位はミリ秒
        let tween = new TWEEN.Tween(from_param)
            .to(to_param, duration)
            .easing(TWEEN.Easing.Linear)
            .on('update', function (_a) {
                let x = _a.x;
                let r = cube_half * Math.sqrt(2); // 中心の回転半径
                let center_angle = 45 + (90 * x); // 現在の中心位置の角度(移動開始時は45°)
                let center_rad = center_angle * Math.PI / 180; // 角度をラジアンに変換
                let current_height = Math.sin(center_rad) * r - cube_half; // 移動中のcube中心の高さ
                let current_move = (cube_half - Math.cos(center_rad) * r) * move_offset; // 移動中のcube中心の位置
                // 移動前のpositionを基準に計算
                mesh03.position[move_axis] = origin_pos[move_axis] + current_move;
                mesh03.position.y = origin_pos.y + current_height;
                let axis = new THREE.Vector3(0, 0, -1); // 回転軸
                let new_q = origin_quaternion.clone();
                let target = new THREE.Quaternion();
                let rad = (Math.PI / 2) * x;
                target.setFromAxisAngle(axis, rad);
                new_q.multiply(target);
                mesh03.quaternion.copy(new_q);
            });
        tween.start();
    }
};
setInterval(next_move, interval);

line.png

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