JavaScript
jQuery
Anime.js
animejs
0
どのような問題がありますか?

投稿日

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

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

ヒラマサを探せ!.png

ブリとヒラマサを見分けてタップするだけの簡単ゲームです。
よかったら遊んでみてくださいm(_ _)m

タイトルなし.gif

要件

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

view

<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>

こんな感じ
image.png

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

ランダムな数を生成する関数設定

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

 // ###### 魚を泳がせる ######
  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

次に、端から端まで泳がしたいので、こんなイメージで配置したいと思います!
画面.png



  // ########  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ファイル↓

.fish{
  position: absolute;
}

fishクラスにアブソリュートを設定してないと位置が変わらないので、cssを設定します。

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

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

  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が終わるごとにメソッドを実行することができる設定です。
ここでは要素の高さをアニメーションが終わるごとに変更することで同じ位置を繰り返し泳がないように設定しました!

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

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

ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
Ryosuke-nakagawa
RUNTEQ24期生/ PF公開中/赤ちゃんの名前決めアプリ「BabyNames」(Rails+LIFF+LINEBOT) サーバーサイドエンジニア目指してRuby on Railsを学習中

コメント

PCやiPad等、画面横幅が大きめの環境では泳いでいる魚が途中で消滅してしまい、不自然な感じがしました。
移動距離を1000固定にされているようですが、画面の横幅に応じて加減すると良いかと思います。


スマホの場合、画面に対する指の動かし方によっては画面全体が引きずられてしまい操作しにくいので、スクロール抑制をしておくといいと思います。

window.addEventListener('touchmove', e => {
  e.preventDefault();
}, { passive: false });

魚の移動に合わせてちらちら表示されるスクロールバーが目障りなので、position: absolute;position: fixed;にするといいかと思います。

0
どのような問題がありますか?
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
記事投稿イベント開催中
新人プログラマ応援 - みんなで新人を育てよう!
~
データに関する記事を書こう!
~
0
どのような問題がありますか?
ユーザー登録して、Qiitaをもっと便利に使ってみませんか

この機能を利用するにはログインする必要があります。ログインするとさらに下記の機能が使えます。

  1. ユーザーやタグのフォロー機能であなたにマッチした記事をお届け
  2. ストック機能で便利な情報を後から効率的に読み返せる
ユーザー登録ログイン
ストックするカテゴリー