モーションライブラリTweenMAXとThree.jsを併用してみる

posts_photo

TweenMax

少しずつThree.jsの使い方をかじっている今日この頃なんですが、オブジェクトをアニメーションさせる際にthree.jsだけでアニメーションの記述を書くとどうしてもやりづらいなと思っていました。

そこで先人の方々のコードを見ているとどうもTweenMaxを使っている方が多い模様。そこで下記のICS MEDIAさんの記事を参考にどうやって併用するかを解読してみました。
高機能なモーション制作用JSライブラリTweenMaxを使ったタイムリマップ表現

用意するもの

Three.jsとTweenMaxを普通に読み込みます。script.jsは処理の記述用です。

<script src="js/TweenMax.min.js" type="text/javascript"></script>
<script src="js/three.min.js" type="text/javascript"></script>
<script src="js/script.js" type="text/javascript"></script>

シンプルな使い方

併用して使う時の考え方は、Three.jsのレンダーループでは描画のアップデートをするだけにして、オブジェクトのアニメーション部分はループの外でTweenMaxに任せます。

var webgl = function(){
  var scene = new THREE.Scene();
  //カメラの設定
  var width = 600;
  var height = 400;
  var fov = 60;
  var aspect = width / height;
  var near = 1;
  var far = 1000;
  var camera = new THREE.PerspectiveCamera(fov,aspect,near,far);
  camera.position.set(0,0,90);

  //DOMに設置
  var renderer = new THREE.WebGLRenderer();
  renderer.setSize(width,height);
  renderer.setClearColor(0xdddddd, 1.0);
  document.body.appendChild(renderer.domElement);

  //光源の追加
  var directionalLight = new THREE.DirectionalLight(0xffffff);
  directionalLight.position.set(0,0.7,0.7);
  scene.add(directionalLight);

  //立方体の情報を設定。
  var parameters = { 
    side: THREE.DoubleSide,
    color: 0xffffff
  };
  var geometry = new THREE.CubeGeometry(10,10,10);
  var material = new THREE.MeshPhongMaterial(parameters);

  //立方体を8つを一列に配置するパラメーターを設定
  var cube = [];
  var position =[
    [-70,20,0],
    [-50,20,0],
    [-30,20,0],
    [-10,20,0],
    [10,20,0],
    [30,20,0],
    [50,20,0],
    [70,20,0]
  ];

  //立方体の初期配置
  for (var i = 0; i < position.length; i++) {
    cube[i] = new THREE.Mesh(geometry,material);
    cube[i].position.set(position[i][0],position[i][1],position[i][2]);
    scene.add(cube[i]);
  }

  //マウスコントロール用の設定
  var controls = new THREE.OrbitControls(camera, renderer.domElement);

  //レンダーループには画面のアップデートのみ記述
  (function renderLoop(){
    requestAnimationFrame(renderLoop);
    controls.update();
    renderer.render(scene,camera);
  })();

  //アニメーションを担うTweenMaxの記述(Timelineですが)
  var tl = new TimelineMax();
  for (var i = 0; i < cube.length; i++) {
    tl.to(cube[i].position , 2 , {ease: Bounce.easeOut,y:-40,repeatDelay: 2,yoyo:true,repeat: -1} , i*0.5);
    tl.to(cube[i].rotation , 5 , {x:4.7,repeat: -1,ease:Power0.easeNone} , i*0.5);
  };
};
window.addEventListener('DOMContentLoaded', webgl, false);

今までアニメーションさせる際はループの中に+dxなどループごとに値を加算させるやり方で行なっていましたが、これだとうまくイージングかけるのも一苦労で…。

TweenMaxはDOMだけでなく数値そのものを扱うアニメーションライブラリなので、Three.js内のオブジェクトのプロパティに対しても有効なのが目からウロコでした。
オブジェクト.positionでxプロパティを指定してX軸をアニメーションさせたり、オブジェクト.rotationでy軸を指定してY軸方向に回転させたりすることが出来ました。
これらが出来ればあとは応用でいろいろな事が出来そう!

タイムリマップ効果も試してみました

ICSメディアさんを参考にタイムリマップ効果も試して見ました。
前述のコードのfor文の後に下記のコードを追加してタイムラインの速度を操作します。

//タイムラインで2秒時点になったら1/10のスピードに。
//その後、正規のタイムラインで2.5秒時点になったら通常スピードに戻す。
tl.addCallback(function () {
  tl.timeScale(0.1);
}, 2);
tl.addCallback(function () {
  tl.timeScale(1);
}, 2.5);

すごく簡単に出来ました!楽しいです。
タイムリマップの使いどころとしては、まずは魅力的なアニメーションありき、その上で演出上強調したい部分をスローモーションにするなど、前提条件がきちっとしてこそ生きる手法かなと思います。
映画やCM的な3Dを作るのはすごく大変だと思いますが、ロゴのモーショングラフィックスやうまいカメラワークに使用すれば使う機会を作れる気がします。

今回はThree.jsとTweenMaxの併用を紹介しました。これならアニメーションの順番制御も簡単だしイベントに紐づけて動かすことも出来るし夢は広がりますね!


初めてのThree.js 第2版 ―WebGLのためのJavaScript 3Dライブラリ