CreateJS で画像の表示、particleの発生とマウスの追従

CreateJS で画像の表示、particleの発生とマウスの追従をさせました。
こんな感じで...
<img src=https://qiita-image-store.s3.amazonaws.com/0/72056/7a5a94b7-eb4a-d43a-22b1-9c162d8e07fe.gif width=50% "frog">

カエルが持っている松明をParticleJSでめらめらと燃やしています。
マウスクリックして画像の表示 -> マウスを押しながらドラッグでメラメラ -> 離すと鎮火(?)
します。
最後に記載しているコードに沿った説明を記載するので、そちらを踏まえながらご覧頂ければと思います。


カエルの画像は[ダ鳥獣戯画]("http://www.chojugiga.com/2017/04/03/da1choju2_0018/")の素材をお借りしました。



# stageの作成

htmlにidを設定したcanvasを置いて、実装していきます。

```html:html
<canvas id="myCanvas"></canvas>
```

```javascript:javascript
  // Stageオブジェクトを作成。
  stage = new createjs.Stage("myCanvas");
```

# スマホのタッチ対応
createjsは以下のように書くだけで、タッチ対応デバイスの際にmouseのXY座標がタッチしたXY座標になります。

```javascript:javascript
  // タッチ操作をサポートしているブラウザーならタッチ操作を有効
  if(createjs.Touch.isSupported() == true){
      createjs.Touch.enable(stage)
  }
```

# Mouse対応
MouseOverとMouseOutは負荷が高くデフォルトでは止められているので、`stage.enableMouseOver()`メソッドで有効にします。

```javascript:javascript
stage.enableMouseOver()
```

# 画像について
ParticleJSはCreateJSを使用しているので、画像の読み込みもCreateJSで実装します。
（そもそもCanvasのdrawImageメソッドと併用しても、レイヤーが重なって表示されているのか描画されませんでした。)
## 画像の読み込みと表示
画像の読み込みにはBitmapオブジェクトを作成します。
`var img = new createjs.Bitmap('testImage.png');`みたいな感じで、引数に画像ファイル名が指定できます。

しかしながら、画像が表示される前にプログラムがはしってしまい、画像が表示されないということがおこります。

なので、読み込みたい画像を`queue.loadManifest()`で設定し、画像が完全に読み込まれた後にはしる`queue.addEventListener("complete", function(e){}`のなかにBitmapオブジェクトの作成処理を書きます。

```javascript:javascript
  //キューオブジェクトを作成
  queue = new createjs.LoadQueue();
  
  //画像の読み込み
  queue.loadManifest([
    {id: "image_1", src: "img/frog.png"}
    ]);

  //画像が読みこまれた後の処理
  queue.addEventListener("complete", function(e){

    imageEmitter = new createjs.Bitmap(queue.getResult("image_1"));
    
    //stageに表示
    stage.addChild(imageEmitter);
    
   });

```

※ queueの書き方にするとサーバーにupしないと表示されないようなので、XAMPPなりMAMPなりgulpなり...ローカル環境で確認する必要があるようです。

複数の画像を表示させたいときは、[CreateJSでcanvasに複数の画像を読み込み表示する方法]("https://qiita.com/pikoshimame/items/62dc2681ae598dfdefff")を参照。

## 画像の基準点
画像の左上が(0.0)を指します。
今回はmouseのXYとparticleEmitterのXY座標が良い感じの位置にくるように、showImage関数内で位置調整をしています。

画像の右上からparticleを発生させたい場合は画像の幅を取得して、位置調整をします。
```javascript:javascript
    //画像の右上からparticleを発生させたい場合は画像の幅を取得
    //showImage関数内でemitterの位置を調節する
    //pibotX = imageEmitter.image.width*imageEmitter.scaleX;
```

# tickイベント
tick イベントを使えば定期的に関数を呼ぶことが可能です。

```javascript:javascript
createjs.Ticker.addEventListener("tick", handleTick);
```
と書けば、handleTick関数が定期的に呼ばれていることになります。
一度呼ばれてしまうと呼ばれ続けるので、描画を停止したいときは

```javascript:javascript
createjs.Ticker.removeEventListener('tick');
```
と記述します。

## フレームレート
tickイベントはデフォルトでは24fで呼ばれ、変更も可能です。


```javascript:javascript
createjs.Ticker.setFPS(30);
```

60fにしたければ、ブラウザの画面更新頻度(ほぼ60f)を使用すると、滑らかにアニメーションができるようです。


```javascript:javascript
createjs.Ticker.timingMode = createjs.Ticker.RAF;
```
RAFはRequstAnimationFrameの略。


#particleの処理
[particleDevelop]("http://ics-web.jp/projects/particle-develop/")のサイトへいき、paticleを作ります。
摩擦のパラメーターとあげるとparticleが同じ位置に留まってくれるようになるので、ねっとりした動きになります。
右上の「パラメータを保存」アイコンをクリックしてJSONをコピーして、// パラメーターJSONのコピー＆ペーストと書いているところにコピペします。



# 全体のコード

```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>松明</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>

<div class="wrapper">
<canvas id="myCanvas"></canvas>
</div>

<script src="js/jquery.min.js"></script>
<script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>
<!-- パーティクルシステムのライブラリー読み込み -->
<script src="https://cdn.rawgit.com/ics-creative/ParticleJS/release/0.1.3/libs/particlejs.min.js"></script>

<script>

var particleSystem;
var stage;
var imageEmitter;
//var pibotX;
var queue;
var isMouseDown  = false;

// ウィンドウのロードが終わり次第、初期化コードを呼び出す
window.addEventListener("load", function () {

  // Stageオブジェクトの作成
  stage = new createjs.Stage("myCanvas");
  
  //キューオブジェクトを作成
  queue = new createjs.LoadQueue();

  // タッチ操作をサポートしているブラウザーならタッチ操作を有効
  // if(createjs.Touch.isSupported() == true){
  //     createjs.Touch.enable(stage)
  // }
  
  stage.enableMouseOver();

  //画像の読み込み
  queue.loadManifest([
    {id: "image_1", src: "img/frog.png"}
    ]);

  //画像が読みこまれた後の処理
  queue.addEventListener("complete", function(e){

    imageEmitter = new createjs.Bitmap(queue.getResult("image_1"));
    
    //スケールの調整
    imageEmitter.scaleX = 0.3
    imageEmitter.scaleY = 0.3

    //画像の右上からparticleを発生させたい場合は画像の幅を取得
    //pibotX = imageEmitter.image.width*imageEmitter.scaleX;
    
    //stageに表示
    stage.addChild(imageEmitter);
    
    // フレームレートの設定
    createjs.Ticker.timingMode = createjs.Ticker.RAF;

    //マウスダウンした時の処理
    stage.addEventListener('stagemousedown', function(e){

        isMouseDown = true;

        // パーティクルシステムのオブジェクトを作成
        createParticle();

        //画像の表示
        showImage();

        stage.update();

    })

    //マウスムーブしている時
    stage.addEventListener('stagemousemove', function(e){
        
      if(isMouseDown === true){
        //マウス位置に従って、パーティクル発生位置とカエルの位置を更新する
        //一度呼び出されたら呼ばれ続ける
        createjs.Ticker.addEventListener("tick", handleTick);
        }
    })

    //マウスアップした時
    stage.addEventListener('stagemouseup', function(e){
    
      stage.removeChild(particleSystem.container);
      
      //tickイベントを停止
      createjs.Ticker.removeEventListener('tick');
    })
  });
});


// パーティクルシステム作成
function createParticle(){

  particleSystem = new particlejs.ParticleSystem();

  // パーティクルシステムの描画コンテナーを表示リストに登録
  stage.addChild(particleSystem.container);

  // Particle Develop から書きだしたパーティクルの設定を読み込む
  particleSystem.importFromJson(
    // パラメーターJSONのコピー＆ペースト ここから--
    {
        "bgColor": "#00000",
        "width": 693,
        "height": 397,
        "emitFrequency": 195,
        "startX": 352,
        "startXVariance": 30,
        "startY": 306,
        "startYVariance": 0,
        "initialDirection": 27.5,
        "initialDirectionVariance": 250,
        "initialSpeed": "3.8",
        "initialSpeedVariance": "7.4",
        "friction": 0.1065,
        "accelerationSpeed": "0.142",
        "accelerationDirection": "275.8",
        "startScale": 0.44,
        "startScaleVariance": 0.5,
        "finishScale": "0",
        "finishScaleVariance": "0",
        "lifeSpan": 87,
        "lifeSpanVariance": 10,
        "startAlpha": "1",
        "startAlphaVariance": "0",
        "finishAlpha": "0",
        "finishAlphaVariance": 0.5,
        "shapeIdList": [
            "blur_circle"
        ],
        "startColor": {
            "hue": "17",
            "hueVariance": 54,
            "saturation": "91",
            "saturationVariance": 0,
            "luminance": "56",
            "luminanceVariance": "16"
        },
        "blendMode": true,
        "alphaCurveType": "1",
        "VERSION": "0.1.3"
    }
    // パラメーターJSONのコピー＆ペースト ここまで---
  );

}


function showImage(){
  //カエルの位置
  imageEmitter.x = stage.mouseX-10;
  imageEmitter.y = stage.mouseY-50;
}

function handleTick() {

  //マウス位置に従って、パーティクル発生位置とカエルの位置を更新する
  //パーティクルの位置を調節する
  particleSystem.startX = stage.mouseX;
  particleSystem.startY = stage.mouseY;

  //カエルの位置
  showImage();

  // パーティクルの発生・更新
  particleSystem.update();

  // 描画を更新する
  stage.update();
}

</script>
<script type="text/javascript">
  //canvasのサイズ指定
  var w = $('.wrapper').width();
  var h = w * 1.32;
  $('#myCanvas').attr('width', w);
  $('#myCanvas').attr('height', h);
</script>
</body>
</html>

```

#参考サイト
[CreateJSでcanvasに画像を読み込み表示する方法]("https://qiita.com/pikoshimame/items/5a793e5db804ffc4ad2b")
[CreateJS のマウスオーバー/マウスアウトの実装方法]("https://ics.media/tutorial-createjs/mouse_over.html")
[CreateJS の Ticker の使い方 - ICS MEDIA]("https://ics.media/tutorial-createjs/ticker.html")
[createjs（0.7.1）のTimerFiredを完全に止める方法]("https://qiita.com/svartalfheim/items/ddbfaffd22705182fb58")
[Webサイトに華やかな表現を！ HTML5用パーティクルライブラリ「ParticleJS」を公開]("https://ics.media/entry/11172")
[canvasのサイズ指定]("https://qiita.com/ShinyaOkazawa/items/9e662bf2121548f79d5f")