物理エンジン「Matter.js」でCanvasアニメーションの質感をアップさせる
スマートフォンやタブレット端末の普及により、
Webページでは、使用感の向上のためにアニメーションの必要性が増しています。
しかも、使用感向上のためには、時間を埋めるためのアニメーションではなく、
普段現実で体験する動きの再現することで、ストレスを感じさせないことが重要になってきます。
そこで自然な動きを再現する物理エンジンが必要となる場合が出てきます。
Matter.jsを使うと、Canvasに簡単に物理エンジンを導入することができます。
Matter.jsは数あるJavaScriptの物理エンジンAPIの中では軽量で、
スマホなどでも軽快に動作するというメリットがあります。
以前もご紹介したことがありますが、2016年時点で、推奨される使用方法が以前と変わっていたので、
改めて導入の基本を調べてみました。
↓簡単なDEMO
DEMO
↓おまけのDEMO
DEMO
以前もご紹介したことがありますが、
若干APIの仕様が変わっていましたので、改めてご紹介いたします。
導入方法
手順
- Matter.jsをダウンロードして、HTMLに読み込む
- Canvasを設置する要素を準備
- Matter.jsの基本設定
- 要素を作成してMatter.jsのWorldに追加
- 物理エンジン・描画を開始
1. Matter.jsをダウンロードして、HTMLに読み込む
公式サイトの「Clone or Download」というボタンから、Download ZIPを選択してファイルをダウンロードします。
ダウンロードしたファイルの「build」というフォルダに「matter.min.js」が入っているので、
こちらをサイトに設置して、以下のようにHTMLで読み込みます。
1 | <script src="js/matter.min.js"></script> |
2. Canvasを設置する要素を準備
1 | <div id="canvas"></div> |
Matter.jsでは、指定した要素にCanvasを追加することで物理エンジンを実装しますので、Canvasを設置する要素を予め準備しておきます 。
body直下に直接設置する場合は、準備する必要はありません。
3. Matter.jsの基本設定
いよいよ、Matter.jsのAPIを使っていきます。
まず、Matter.jsの基本的なAPIを呼び出します。
1 2 3 4 5 6 | // Matter.jsのAPIの読み込み var Engine = Matter.Engine, Render = Matter.Render, World = Matter.World, Bodies = Matter.Bodies, MouseConstraint = Matter.MouseConstraint; |
以前はEngineとRenderはEngineにまとめられていましたが、今は別々に分けて使うことが推奨されています。
次にEngineとRenderを生成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // create an engine var engine = Engine.create(); // create a renderer var render = Render.create({ element: document.getElementById("canvas"), //Canvasを設置する要素を指定 engine: engine, //生成したEngineを指定 options: { width: 640, //CanvasのWidth height: 480, //CanvasのHeight pixelRatio: 2, //Pixel比; スマホ用に2にする background: "rgba(0, 0, 0, 0)", //背景色 wireframes: false //ワイヤーフレームモードをOFFにする } }); |
Renderの生成での設定は、以前はEngineの設定で行われていましたが、
将来的に、Engine内ではこの設定が廃止されるようなので、今後はこのように設定する必要があります。
Render.create()のオプションは以下のサイトでご紹介いただいていました。
要素をマウスやタッチで操作できるようにしたい場合は、以下のコードを記述します。
1 2 3 4 5 6 7 8 9 | var mousedrag = MouseConstraint.create(engine, { element: canvas.childNodes[0], //マウス操作を感知する要素を指定(DEMOでは生成したcanvasを指定) constraint: { render: { strokeStyle: "rgba(0, 0, 0, 0)" //マウス操作の表示を隠す } } }); World.add(engine.world, mousedrag); |
デフォルトではマウス操作の様子が線として描画されるため、表示したくないときはconstraint.render.strokeStyleを透明色にします。
4. 要素を作成してMatter.jsのWorldに追加
Matter.jsでは、BodiesというAPIで基本的な図形の要素を生成することができます。
1 2 3 4 5 | //円の要素 Bodies.circle(X座標, Y座標, 半径, [optins]); //四角の要素 Bodies.rectangle(X座標, Y座標, 横幅, 縦幅, [optins]); |
optionsは以下のサイトでご紹介いただいていました。
生成した要素はWorld.add()でWorldに追加する必要があります。
1 2 | var ball = Bodies.circle(100, 100, 50); World.add(engine.world, ball); |
まとめて追加したい場合は、以下のように配列で追加することも可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 | //ボールを多数ランダムに生成 for(var i = 0; i < 20; i++) { bodies.push(Bodies.circle(Math.random() * (canvasWidth - 0) + 0, Math.random() * (canvasHeight - 0) + 0, Math.random() * (75 - 25) + 25, circleOptions)); //円の要素は Bodies.circle(X座標, Y座標, 半径, [optins]) で作成できる } bodies.push(Bodies.rectangle(0, 0, canvasWidth*2, 1, { isStatic: true })); bodies.push(Bodies.rectangle(0, canvasHeight, canvasWidth*2, 1, { isStatic: true })); bodies.push(Bodies.rectangle(0, 0, 1, canvasHeight*2, { isStatic: true })); bodies.push(Bodies.rectangle(canvasWidth, 0, 1, canvasHeight*2, { isStatic: true })); //四角の要素は Bodies.rectangle(X座標, Y座標, 横幅, 縦幅, [optins]) で作成できる // add all of the bodies to the world World.add(engine.world, bodies); |
重力を操作したい場合は、以下のように指定することで重力を変更できます。
1 | engine.world.gravity.y = 0; //重力を0に設定 デフォルトは1 |
5. 物理エンジン・描画を開始
最後にEngine.run()とRender.run()を実行すれば、描画が開始されます。
1 2 3 4 5 | // run the engine Engine.run(engine); // run the renderer Render.run(render); |
matter-js 0.11.0 Physics Engine API Docs
詳細な使用方法は上記の公式Documentで確認できますが、
あまり親切とはいえない構成なので、
初めは以下のwikiを参考にすることをオススメいたします。
Home · liabru/matter-js Wiki · GitHub
おまけ
スマホやタブレットの場合、
傾きのセンサーと重力の方向を合わせることで、
傾きに応じた自然な動きを実装することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | var deviceOrientation = window.orientation; //デバイスの傾きを取得 //デバイスが動くたびに実行 window.addEventListener("devicemotion", function(e){ //重力加速度(傾き)を var xg = e.accelerationIncludingGravity.x / 10; var yg = e.accelerationIncludingGravity.y / 10; switch (deviceOrientation) { case 0: engine.world.gravity.x = xg; engine.world.gravity.y = -yg; break; case 90: engine.world.gravity.x = -yg; engine.world.gravity.y = -xg; break; break; case -90: engine.world.gravity.x = yg; engine.world.gravity.y = xg; break; case 180: engine.world.gravity.x = -xg; engine.world.gravity.y = yg; } }, true); //デバイスの傾きを取得 window.addEventListener("orientationchange", function(){ deviceOrientation = window.orientation; }, false); |
参考サイト
Author Profile
NINOMIYA
Webデザイナー兼コーダー出身のフロントエンド開発者です。 UXデザインやチーム開発の効率化など、勉強中です。
SHARE