Help us understand the problem. What is going on with this article?

matter.js × 加速度センサーでweb上で物体をシェイクさせよう!

More than 1 year has passed since last update.

matter.js

どうも、OthloTechのちーず(@cheez921)です。
OthloTech Advent Calendar 今年2回目の投稿ということで内容をがらりとかえまして、芸工祭webサイト作成時にお世話になったmatter.jsの活用法について話したいと思います。
少し古いライブラリだけど、なかなか優秀です!!

matter.jsとは

matter.jsは、javascript製の物理演算エンジンです。
web上の物体の動きに対して物理演算が必要なとき、プログラムを全部自分で書くのはなかなか面倒ですよね。
matter.jsではそんな面倒なコードを書かずとも、反発係数や密度などを簡単なプログラムで設定でき、理想的な物体の動きが実装できます。

  • github
  • 公式ホームページ
  • DEMO
    DEMOページでは様々なサンプルが公開されており、パラメータをいじったり、自分が生成したマテリアルを検索したりすることが可能です。

g.gif

matter.jsをつかってみよう!

1. インストール

公式Githubにてインストールが可能です。
ダウンロードしたzipファイルに入っているmatter.jsもしくはmatter.min.jsを読み込んでください。

2. 使用するメソッドを読み込む

Engine,Render,Worldのメソッドは必ず読み込み、EngineやRenderを準備しましょう。

  // module aliases
  var Engine = Matter.Engine,
      Render = Matter.Render,
      World = Matter.World,
      Bodies = Matter.Bodies;

  // create an engine
  var engine = Engine.create();

  var width =  window.innerWidth;
  var height =  window.innerHeight;

  // create a renderer
  var render = Render.create({
      element: document.getElementById("canvas"),
      options: {
        width: width,
        height: height,
        pixelRatio: 2, //Pixel比; スマホ用に2にする
      },
      engine: engine
  });

2. マテリアルの追加

まずは、床や壁を生成しましょう。
床だけでも良いが今回はシェイクするということで、壁と天井と床を生成します。

  //壁の生成
  bodies.push(Bodies.rectangle(0, 0, width*2, 80,{ isStatic: true}));
  bodies.push(Bodies.rectangle(0, height, width*2 + 10, 30, { isStatic: true }));
  bodies.push(Bodies.rectangle(0, 0, 40, height*2, { isStatic: true }));
  bodies.push(Bodies.rectangle(width, 0, 40, height*2, { isStatic: true }));

コードの説明をちょっとします。

bodies.push(
    //四角のマテリアルを追加
    Bodies.rectangle( 
      0, //x座標
      0, //y座標
      width*2, // width 
      80, // height
      //option
      { 
        isStatic: true //静的かどうか
      }
    )
  );

ざっくりとこんな感じです。

次に中のマテリアルを追加します。
30個の円をばらばらに落下するように準備しました。

for(var i = 0; i < 30; i++) {
  bodies.push(
    Bodies.circle(
      Math.random() * (width - 0) + 0, //x座標
      Math.random() * (height - 440) + 440, //y座標
      20, //半径
      {
        density: 0.0005, //密度
        frictionAir: 0.02, //空気抵抗
        restitution: 0.8, //反発
        friction: 0.1, //摩擦
        }
      }
    )
  )
}

そして生成したマテリアルを用意したマテリアルをレンダーしましょう。

  // add all of the bodies to the world
  World.add(engine.world, bodies);

  // run the engine
  Engine.run(engine);

  // run the renderer
  Render.run(render);

これでmatter.jsで動かしたい物体の準備は完了です。
とっても簡単ですよね!
だいたいこんな感じのものが出来上がります。

スクリーンショット 2017-12-21 22.57.07.png

加速度を取得しよう!

今回はmatter.jsについて話したかったので、この辺の詳細は割愛させていただきます。
もしデバイスの加速度センサーについてもっと詳細が知りたかった場合、こちらの記事を参考にしてください。
DeviceOrientation Eventについて

実際のコードはこちらです。
先ほどのコードより前に書いてください。

var deviceOrientation = window.orientation; //デバイスの傾きを取得

  //デバイスが動くたびに実行 : devicemotion
  window.addEventListener("devicemotion", function devicemotionHandler(event) {


    //重力加速度 (物体の重力を調節)
    var xg = event.accelerationIncludingGravity.x / 10;
    var yg = event.accelerationIncludingGravity.y / 10;

    // 傾きに応じて重力を調節
    switch (deviceOrientation) {
      case 0:
        engine.world.gravity.x = xg + event.acceleration.x;
        engine.world.gravity.y = -yg + event.acceleration.y;
        break;
      case 90:
        engine.world.gravity.x = -yg - event.acceleration.x;
        engine.world.gravity.y = -xg + event.acceleration.x;
        break;
      case -90:
        engine.world.gravity.x = yg + event.acceleration.x;
        engine.world.gravity.y = xg - event.acceleration.x;
        break;
      case 180:
        engine.world.gravity.x = -xg - event.acceleration.x;
        engine.world.gravity.y = yg - event.acceleration.x;
    }

    // androidとiOSは加速度が真逆なのでその対応
    if ( window.navigator.userAgent.indexOf('Android') > 0 ) {
      engine.world.gravity.x = - engine.world.gravity.x;
      engine.world.gravity.y = - engine.world.gravity.y;
    }
  });

以上で完成です!
コードが汚いですね。笑
もっと最適なコードがありましたらコメントをお願いいたします。

完成作

以上のコードに、optionでマテリアルに画像を貼ったり、UIをリッチにしたらこんな感じで導入できました。

芸工祭2017
⚠︎スマホでみてください。

(かなり私情ですが、我ながら芸術工学部らしくて気にっています。)

最後に

matter.jsは割とGithubのstar数もあるし予想以上に重くないのに、日本ではあまり使われていない様子でした。
たまにはこのようなクリエイティブなライブラリでも導入して、webサイトでガンガンに遊べるものをつくってみてはいかがでしょうか!

cheez921
フロントエンドエンジニアになりたい新卒2年生
a-hikkoshi
当社は、親会社である株式会社エイチームの経営理念をそのままに、引越しの比較サービス開始以降、大切にしてきた「三方よし」の理念を基本として、世の中に求められるサービスの創造を目指します。 一緒に働けるエンジニアを募集しております。下記URLよりご応募ください。 https://bit.ly/3lwf7QJ
https://hikkoshi.a-tm.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away