魚を繰り返し泳がしてみた[Javascript・anime.js]

まず完成形をイメージしてもらいたいので、
作ったアプリを紹介します。

![ヒラマサを探せ！.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/79c5688e-fc9a-c253-b73d-700d27e60c5a.png)

https://find-hiramasa-app.herokuapp.com/

ブリとヒラマサを見分けてタップするだけの簡単ゲームです。
よかったら遊んでみてくださいm(_ _)m※現在heroku有料化に伴い、運用を停止しています。

![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/3651de05-a394-3374-67f7-e391a05ef07d.gif)


## 要件

* 魚がそれぞれ別のスピードで泳ぐこと
* 魚が画面端から端まで泳ぐと、縦方向にランダムに配置転換されてまた泳ぎ出すこと
※タップしてから結果表示はこの記事では紹介しません。

## view
```html
<div class="container">
    <img id="hiramasa" class="fish" src="/assets/hiramasa.png">
    <img class="fish" src="/assets/buri.png">
    <img class="fish" src="/assets/buri.png">
    <img class="fish" src="/assets/red_fish.png">
    <img class="fish" src="/assets/aji.png">
    <img class="fish" src="/assets/sawara.png">
    <img class="fish" src="/assets/aji.png">
    <img class="fish" src="/assets/sawara.png">
</div>
```
こんな感じ
<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/59bf97e7-a97c-c5b6-87a3-92d7be3d788c.png">

## Javascript
```javascript
import anime from "animejs"

$(window).on("load",function(){

  // ###### 引数で渡した範囲内のランダムな整数を生成するための関数 ######
  var getRandomInt = function(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  };
```


## animejsを読み込み
animejsを使用した理由は、以下です。
・直線だけでなくイカを泳がす動きも試したかったので、少し自由度があること
・重くない
・ドキュメントや使用例が豊富

読み込み手順詳細はgithubで
https://github.com/juliangarnier/anime

## ランダムな数を生成する関数設定
配置の転換やアニメーションの速さを変更するのに必要なのではじめに関数を設定しておきます。

```javascript
 // ###### 魚を泳がせる ######
  var fishElements = document.querySelectorAll(".fish");
  fishElements.forEach(fish => {
    anime.speed = 0.6; //animeの全体のスピードの調整
    anime({
      targets: fish, //動かす対象
      translateX: 1000,//移動距離
      loop: true,// 繰り返し
      duration: getRandomInt(1500,5000),//どのくらいアニメーションを継続するか
      easing: 'easeInQuad',//動き
      delay: getRandomInt(0,300),//遅延
    });
  })
```
さっそく魚を泳がせます。

fishクラスを取得。eachで回して、それぞれにアニメーションを付与しています。

animejs全体の速度を設定（難易度設定に使用）
`anime.speed = 0.6`

animejsの個別の設定はanime({})の中にそれぞれ設定値を入れていきます。

動くスピードをばらつかせるために、
`duration: getRandomInt(1500,5000)`とすることで、
継続時間を1500〜5000の間でランダムに設定しています。
動く距離は同じで継続時間が変わると、動くスピードが変わっていきます。

魚たちにバラバラのタイミングで泳ぎ出して欲しいので、遅延をランダムで設定します。
`delay: getRandomInt(0,300)`

ここまでで、魚をタイミングをずらして泳がすことに成功しました。

![animejsのみ適用.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/f558e3a4-4993-9989-153e-16f487269160.gif)

次に、端から端まで泳がしたいので、こんなイメージで配置したいと思います!
![画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/ddeb5b7d-4447-b092-df0c-9a2083ed0fc8.png)

```javascript


  // ########  containerクラスの高さ・幅を取得  #########
    // 要素の取得
  var $container = $('.container'),
  containerHeight = $container.height();
  
    // ####### 魚をそれぞれをランダムに配置 #######
  var $fish = $('.fish')
  $.map($fish, function(item) {
    var $item = $(item), // fishクラスの要素が1番目から順に入ってきます
    topPos = getRandomInt(0, containerHeight), // 130〜コンテナの高さの間でtopの座標を設定
    leftPos = getRandomInt(-700, -200); // -700〜-200の間でleft の座標を設定
    // 取得したランダム座標を設定
    $item.css({
      top: topPos,
      left: leftPos
    });
  });
 
```

上下方向に画面外に出てしまうと見えないので、画面のcontainerの要素の高さを取得して、

fishクラスをmapで回します。
getRandomInt(最小値,最大値)となるように関数を作ったので

高さ方向は
`topPos = getRandomInt(130, containerHeight)`
で、130以上containerの高さ以下でランダムに値を振り分けます。

横方向は左画面外から動いてほしいので、
`leftPos = getRandomInt(-700, -200)`
で画面左外側に配置します。

あとはjavascriptからcssを調整して、高さを変更します。

cssファイル↓
```css
.fish{
  position: absolute;
}
```
fishクラスにアブソリュートを設定してないと位置が変わらないので、cssを設定します。

これで画面の外から外まで移動するようになったはずです！
幅を調整したい場合はanimejsのtranslateXを変えるか、containerクラスのwidthを使ってゴニョゴニョすると良いと思います。

## 魚が泳ぐ位置をアニメーションごとに変えたい

```javascript
  anime({
      targets: fish,
      translateX: 1000,//移動距離
      loop: true,//繰り返し
      duration: getRandomInt(1500,5000),//どのくらいアニメーションを継続するか
      easing: 'easeInQuad',//動き
      delay: getRandomInt(0,300),//遅延
      //    ↓ここから追加↓
      loopComplete: function(anim) {
        // 取得したランダム座標を設定
        fish.style.top = `${getRandomInt(150,containerHeight)}px`
      }
      //    ↑ここまで↑
    });
```
loopCompleteはloopが終わるごとにメソッドを実行することができる設定です。
ここでは要素の高さをアニメーションが終わるごとに変更することで同じ位置を繰り返し泳がないように設定しました！

魚を泳がすのはみてて心が安らぎます。
ぜひやってみてください。

最後まで見ていだだきありがとうございました！