particles.jsのアニメーション切替問題!

Particlesjs Switch

Webサイトにリッチな演出を加えるライブラリのひとつに particles.js があります。星屑のようなパーティクルが舞う背景は、とても華やかで目を引きますよね。しかし、アニメーションを複数パターン切り替えて使いたい場合、注意しなければならない落とし穴があります。

複数アニメーション切替で起きる問題

particles.js は一度ロードすると インスタンスを保持したまま動き続けます。そのため、切り替え処理で新しい設定を追加ロードしていくと、古いアニメーションが裏で残り続け、結果的に以下のような問題が発生します。

  • 背景が二重・三重に重なってチラつく
  • CPU/GPU の負荷が増大
  • スマホだと一気に動作が重くなる

解決策:インスタンスの完全破棄

この問題を解決するには、切り替えのたびに既存インスタンスを破棄する処理 を必ず挟む必要があります。以下の関数を用意すると安全です。

app.js
//////////////////////アニメーションを完全破棄////////////////////
function clearParticles() {
  if (window.pJSDom && window.pJSDom.length > 0) {
    try {
      window.pJSDom[0].pJS.fn.vendors.destroypJS(); // ←これが核
      window.pJSDom = [];
      console.log("Particles.js 初期化完了");
    } catch (e) {
      console.warn("Particles.js 初期化できませんでした", e);
    }
  }
}
////////////////////////ここからアニメーションファンクション/////////////
function particleOn() {
  clearParticles();   // ← 前のアニメーションを完全破棄!
  particlesJS('particles-js',
    {
      "particles": {
        "number": {
          "value": 80,
          "density": {
            "enable": true,
            "value_area": 800
          }
        },
        "color": {
          "value": "#ffffff"
        },
        "shape": {
          "type": "circle",
          "stroke": {
            "width": 0,
            "color": "#000000"
          },
          "polygon": {
            "nb_sides": 5
          },
          "image": {
            "src": "img/github.svg",
            "width": 100,
            "height": 100
          }
        },
        "opacity": {
          "value": 0.5,
          "random": false,
          "anim": {
            "enable": false,
            "speed": 1,
            "opacity_min": 0.1,
            "sync": false
          }
        },
        "size": {
          "value": 5,
          "random": true,
          "anim": {
            "enable": false,
            "speed": 40,
            "size_min": 0.1,
            "sync": false
          }
        },
        "line_linked": {
          "enable": true,
          "distance": 150,
          "color": "#ffffff",
          "opacity": 0.4,
          "width": 1
        },
        "move": {
          "enable": true,
          "speed": 6,
          "direction": "none",
          "random": false,
          "straight": false,
          "out_mode": "out",
          "attract": {
            "enable": false,
            "rotateX": 600,
            "rotateY": 1200
          }
        }
      },
      "interactivity": {
        "detect_on": "canvas",
        "events": {
          "onhover": {
            "enable": true,
            "mode": "repulse"
          },
          "onclick": {
            "enable": true,
            "mode": "push"
          },
          "resize": true
        },
        "modes": {
          "grab": {
            "distance": 400,
            "line_linked": {
              "opacity": 1
            }
          },
          "bubble": {
            "distance": 400,
            "size": 40,
            "duration": 2,
            "opacity": 8,
            "speed": 3
          },
          "repulse": {
            "distance": 200
          },
          "push": {
            "particles_nb": 4
          },
          "remove": {
            "particles_nb": 2
          }
        }
      },
      "retina_detect": true,
      "config_demo": {
        "hide_card": false,
        "background_color": "#b61924",
        "background_image": "",
        "background_position": "50% 50%",
        "background_repeat": "no-repeat",
        "background_size": "cover"
      }
    }

  );
}
////////////////////////////////////////////////////////////
function snowOn() {
  clearParticles();   // ← 前のアニメーションを完全破棄!
  // 雪を降らせる
  particlesJS("particles-js", {
    "particles": {
      //シェイプの設定
      "number": {
        "value": 150, //シェイプの数
        "density": {
          "enable": true, //シェイプの密集度の設定許可
          "value_area": 800 //シェイプの密集度
        }
      },
      "shape": {
        "type": "image", //circle、edge、triangle、polygon、star、image から選べる
        "image": {
          "src": "https://kakechimaru.com/wp-content/themes/kakechimaru/image/snow_particlesjs.png", //雪の画像を設定する ※相対パスでも可
        }
      },
      "opacity": {
        "value": 0.7, //透明度
        "random": false, //透明度ランダムの許可
        "anim": {
          "enable": false, //透明度のアニメーションさせるかどうか
          "speed": 1, //アニメーションのスピード
          "opacity_min": 0.1, //透明度の最小値
          "sync": false //シェイプを同時にアニメーションさせるかどうか
        }
      },
      "size": {
        "value": 5, //シェイプの大きさ
        "random": true, //大きさランダムの許可
        "anim": {
          "enable": false, //大きさアニメーションさせるかどうか
          "speed": 20, //スピード
          "size_min": 0.1, //スピードの最小値
          "sync": false //同時にアニメーションさせるかどうか
        }
      },
      // 線の設定
      "line_linked": {
        "enable": false, //線を表示するかどうか
      },
      // 動きの設定
      "move": {
        "enable": true, //シェイプの動かすかどうか
        "speed": 2, //スピード
        "direction": "bottom", //シェイプの動く方向(none、top、top-right、right、bottom-right、bottom、bottom-left、left、top-left から選べる)
        "random": true, // 動きはランダム
        "straight": false, // 動きをとどめない
        "out_mode": "out", //エリア外に出たシェイプの動き(out、bounce から選べる)
        "bounce": false, //跳ね返りなし
        "attract": {
          "enable": true,
          "rotateX": 300,
          "rotateY": 1200
        }
      }
    },
    "interactivity": {
      "detect_on": "canvas",
      "events": {
        //マウスオーバー時
        "onhover": {
          "enable": false, //マウスオーバーの許可
        },
        //クリック時
        "onclick": {
          "enable": false, //クッリクの許可
        },
        "resize": true
      }
    },
    "retina_detect": true
  });
}
////////////////////////////////////////////////////////////
function bubbleOn() {
  clearParticles();   // ← 前のアニメーションを完全破棄!
  particlesJS("particles-js",
    {
      "particles": {
        "number": {
          "value": 28,
          "density": {
            "enable": true,
            "value_area": 789.1476416322727
          }
        },
        "color": {
          "value": "#ffffff"
        },
        "shape": {
          "type": "circle",
          "stroke": {
            "width": 3,
            "color": "#9be1ff"
          },
          "polygon": {
            "nb_sides": 8
          },
          "image": {
            "src": "img/github.svg",
            "width": 100,
            "height": 100
          }
        },
        "opacity": {
          "value": 0.41035677364878176,
          "random": true,
          "anim": {
            "enable": false,
            "speed": 1,
            "opacity_min": 0.1,
            "sync": false
          }
        },
        "size": {
          "value": 43.403120289774996,
          "random": true,
          "anim": {
            "enable": false,
            "speed": 21.57842157842158,
            "size_min": 0.1,
            "sync": false
          }
        },
        "line_linked": {
          "enable": false,
          "distance": 500,
          "color": "#ffffff",
          "opacity": 0.4, "width": 2
        },
        "move": {
          "enable": true,
          // "speed":4.734885849793636,
          "speed": 1.734885849793636,
          "direction": "top",
          "random": false,
          "straight": false,
          "out_mode": "out",
          "bounce": false,
          "attract": {
            "enable": false,
            "rotateX": 2367.442924896818,
            "rotateY": 1104.8066982851817
          }
        }
      },
      "interactivity": {
        "detect_on": "canvas",
        "events": {
          "onhover": {
            "enable": true,
            "mode": "bubble"
          },
          "onclick": {
            "enable": true,
            "mode": "repulse"
          },
          "resize": true
        },
        "modes": {
          "grab": {
            "distance": 503.4965034965035,
            "line_linked": {
              "opacity": 0.5
            }
          },
          "bubble": {
            "distance": 400,
            "size": 4,
            "duration": 0.3,
            "opacity": 1,
            "speed": 3
          },
          "repulse": {
            "distance": 200,
            "duration": 0.4
          },
          "push": {
            "particles_nb": 4
          },
          "remove": {
            "particles_nb": 2
          }
        }
      },
      "retina_detect": true
    }
  );
  var count_particles, stats, update;
  stats = new Stats;
  stats.setMode(0);
  stats.domElement.style.position = 'absolute';
  stats.domElement.style.left = '0px';
  stats.domElement.style.top = '0px';
  document.body.appendChild(stats.domElement);
  count_particles = document.querySelector('.js-count-particles');
  update = function () {
    stats.begin(); stats.end();
    if (window.pJSDom[0].pJS.particles && window.pJSDom[0].pJS.particles.array) {
      count_particles.innerText = window.pJSDom[0].pJS.particles.array.length;
    }
    requestAnimationFrame(update);
  };
  requestAnimationFrame(update);;
}
///////////////////////////////////////////////////////////////
function snow2On() {
  clearParticles();   // ← 前のアニメーションを完全破棄!
  particlesJS('particles-js',
    {
      "particles": {
        //シェイプ数
        "number": {
          //要素内に表示するシェイプの数
          "value": 160,//初期値80
          "density": {
            //シェイプ表示間隔設定
            "enable": true,
            //シェイプ表示間隔指定
            "value_area": 800
          }
        },
        //シェイプ色
        "color": {
          "value": "#ffffff"
        },

        //シェイプの設定
        "shape": {
          //シェイプ形
          "type": "circle", //circle, edge, triangle, polygon, star, image 複数指定["circle", "triangle", "image"]

          //シェイプボーダー設定
          "stroke": {
            //ボーダー幅
            "width": 0,
            //ボーダー色
            "color": "#000000"
          },
          //シェイプの形でpolygonを指定した場合
          "polygon": {
            //ポリゴン角数指定
            "nb_sides": 5
          },

          //シェイプの形でimageを指定した場合
          "image": {
            //画像パス
            "src": "img/github.svg",
            //画像幅
            "width": 100,
            //画像高
            "height": 100
          }
        },

        //シェイプ透過率指定
        "opacity": {
          //透過率指定
          "value": 0.8,//初期値0.5
          //ランダム設定
          "random": false, //true:有効, false:無効

          //透過アニメーション設定
          "anim": {
            //アニメーション設定
            "enable": false, //true:有効, false:無効
            //アニメーション速度
            "speed": 1,//初期値1
            //アニメーション最小透過率
            "opacity_min": 0.1,
            //アニメーション同期
            "sync": false //true:有効, false:無効
          }
        },

        //シェイプサイズ
        "size": {
          //シェイプサイズ指定
          "value": 5,
          //ランダムサイズ
          "random": true, //true:有効, false:無効
          //サイズアニメーション設定
          "anim": {
            //アニメーション設定
            "enable": false, //true:有効, false:無効
            //アニメーション速度
            "speed": 40,//初期値40
            //アニメーション最小サイズ,
            "size_min": 1,
            //アニメーション同期設定
            "sync": false //true:有効, false:無効
          }
        },

        //シェイプを線で繋ぐか
        "line_linked": {
          //線の設定
          "enable": false, //true:有効, false:無効
          //線の間隔
          "distance": 150,
          //線の色
          "color": "#ffffff",
          //線の透過率
          "opacity": 0.4,
          //線の幅
          "width": 1
        },
        //シェイプの動きの設定
        "move": {
          //動きを制御するか
          "enable": true, //true:有効, false:無効
          //動く速度
          "speed": 0.5,
          //動く方向
          "direction": "bottom", //none, top, top-right, right, bottom-right, bottom, bottom-left, left, top-left
          //ランダム設定
          "random": false, //true:有効, false:無効
          //静止状態にする
          "straight": false, //true:有効, false:無効
          //シェイプの動き
          "out_mode": "out", //ボックス内で動かす bounce ボックス外に逃がす out
          "attract": {
            "enable": true,
            "rotateX": 1000,
            "rotateY": 1000
          }
        }
      },
      "interactivity": {
        "detect_on": "canvas",

        //マウスイベント設定
        "events": {
          //マウスオーバー時の処理
          "onhover": {
            "enable": false, //true:有効, false:無効
            "mode": "bubble" //grad:付近のシェイプと線を繋ぐ, bubble:拡大, repulse:拒絶
          },

          //クリック時の処理処理
          "onclick": {
            //クリック時の処理
            "enable": true, //true:有効, false:無効
            //クリック時の処理
            "mode": "push" //push:追加, remove:削除, bubble:拡大, repulse:拒絶
          },
          "resize": true
        },
        //以下でマウスイベント発生時の詳細値を設定
        "modes": {
          "grab": {
            "distance": 300,
            "line_linked": {
              "opacity": 1
            }
          },
          "bubble": {
            "distance": 100,
            "size": 7.5,
            "duration": 2,
            "opacity": 8,
            "speed": 3
          },
          "repulse": {
            "distance": 1
          },
          "push": {
            "particles_nb": 4
          },
          "remove": {
            "particles_nb": 2
          }
        }
      },
      //Retina Display対応
      "retina_detect": true, //true:有効, false:無効
    }
  );
}
///////////////////////////////////////////////////////////
function paperOn() {
  clearParticles();   // ← 前のアニメーションを完全破棄!
  particlesJS("particles-js", { //ここに書くのがHTMLのidに対応するもの
    "particles": {
      "number": {
        "value": 50,//紙吹雪の数
        "density": {
          "enable": false,
          "value_area": 200
        }
      },
      "color": {
        "value": ["#EA5532", "#F6AD3C", "#FFF33F", "#00A95F", "#00ADA9", "#00AFEC", "#4D4398", "#E85298"]//紙吹雪の色の種類
      },
      "shape": {
        "type": "polygon",//形状はPolygon,つまり多角形
        "stroke": {
          "width": 0,
        },
        "polygon": {
          "nb_sides": 4//多角形の角の数
        }
      },
      "opacity": {
        "value": 1,
        "random": false,
        "anim": {
          "enable": true,
          "speed": 20,
          "opacity_min": 0,
          "sync": false
        }
      },
      "size": {
        // "value":5,
        "value": 8,
        "random": true,//サイズをランダムにする
        "anim": {
          "enable": true,
          "speed": 1,
          "size_min": 1,
          "sync": false
        }
      },
      "line_linked": {
        "enable": false,
      },
      "move": {
        "enable": true,
        "speed": 3,//小さくするとゆっくり、大きくすると速くなる
        "direction": "bottom",//落ちる向き
        "random": true,//動きをランダムにするか
        "straight": false,//まっすぐ落ちるかどうか
        "out_mode": "out",//画面の外に出るか
        "bounce": false,//跳ね返るかどうか
        "attract": {
          "enable": false,
          "rotateX": 600,
          "rotateY": 1200
        }
      }
    },
    "interactivity": {
      "detect_on": "canvas",
      "events": {
        "onhover": {
          "enable": false,
        },
        "onclick": {
          "enable": false,
        },
        "resize": true
      },
    },
    "retina_detect": true
  });
}
/////////////////////////////////////////////////////
function sakuraOn() {
  clearParticles();   // ← 前のアニメーションを完全破棄!
  particlesJS("particles-js", {
    "particles": {
      "number": {
        "value": 60,//この数値を変更すると桜の数が増減できる
        "density": {
          "enable": true,
          "value_area": 1121.6780303333778
        }
      },
      "color": {
        "value": "#fff"
      },
      "shape": {
        "type": "image",//形状は画像を指定
        "stroke": {
          "width": 0,
        },
        "image": {
          "src": "./img/sakura.png",//画像を指定
          "width": 420,
          "height": 420
        }
      },
      "opacity": {
        "value": 0.06409588744762158,
        "random": true,
        "anim": {
          "enable": false,
          "speed": 1,
          "opacity_min": 0.1,
          "sync": false
        }
      },
      "size": {
        // "value":8.011985930952697,
        "value": 11.011985930952697,
        "random": true,//サイズをランダムに
        "anim": {
          "enable": false,
          "speed": 4,
          "size_min": 0.1,
          "sync": false
        }
      },
      "line_linked": {
        "enable": false,
      },
      "move": {
        "enable": true,
        "speed": 5,//この数値を小さくするとゆっくりな動きになる
        "direction": "bottom-right",//右下に向かって落ちる
        "random": true,//動きはランダムにしないfalse
        "straight": false,//動きをとどめない
        "out_mode": "out",//画面の外に出るように描写
        "bounce": false,//跳ね返りなし
        "attract": {
          "enable": false,
          "rotateX": 281.9177489524316,
          "rotateY": 127.670995809726
        }
      }
    },
    "interactivity": {
      "detect_on": "canvas",
      "events": {
        "onhover": {
          "enable": false,
        },
        "onclick": {
          "enable": false,
        },
        "resize": true
      }
    },
    "retina_detect": false
  });
}
///////////////////////////////////////////////////////////////
function hotalOn() {
  clearParticles();   // ← 前のアニメーションを完全破棄!
  particlesJS("particles-js", {
    "particles": {
      "number": {
        // "value":50,//この数値を変更するとホタルの数が増減できる
        "value": 80,//この数値を変更するとホタルの数が増減できる
        "density": {
          "enable": true,
          "value_area": 1602.3971861905397
        }
      },
      "color": {
        "value": "#f3fa8b"//色
      },
      "shape": {
        "type": "circle",//形状はcircleを指定
        "stroke": {
          "width": 0,
        }
      },
      "opacity": {
        "value": 1,
        "random": true,//透過をランダムに
        "anim": {
          "enable": false,
          "speed": 1.10115236356258881,
          "opacity_min": 0,
          "sync": false
        }
      },
      "size": {
        "value": 4.005992965476349,
        "random": true,//サイズをランダムに
        "anim": {
          "enable": true,
          "speed": 24.345709068776642,
          "size_min": 0.5,
          "sync": false
        }
      },
      "line_linked": {
        "enable": false,
      },
      "move": {
        "enable": true,
        // "speed":6,//この数値を小さくするとゆっくりな動きになる
        "speed": 1,//この数値を小さくするとゆっくりな動きになる
        "direction": "none",//方向指定なし
        "random": true,//動きはランダムに
        "straight": false,//動きをとどめない
        "out_mode": "out",//画面の外に出るように描写
        "bounce": false,//跳ね返りなし
        "attract": {
          "enable": false,
          "rotateX": 600,
          "rotateY": 600
        }
      }
    },
    "interactivity": {
      "detect_on": "canvas",
      "events": {
        "onhover": {
          "enable": false
        },
        "onclick": {
          "enable": false
        },
        "resize": true
      }
    },
    "retina_detect": true
  });
}
///////////////////////////////////////////////////////////////////////////
function rainOn() {
  clearParticles();   // ← 前のアニメーションを完全破棄!
    particlesJS('particles-js', {
      particles: {
        number: {
          value: 80, // Number of raindrops
          density: {
            enable: true,
            value_area: 800
          }
        },
        color: {
          value: '#ffffff' // White raindrops
        },
        shape: {
          type: 'circle', // Raindrops as circles
        },
        opacity: {
          value: 0.5,
          random: false,
          anim: {
            enable: false,
          }
        },
        size: {
          value: 3, // Size of raindrops
          random: true,
          anim: {
            enable: false,
          }
        },
        line_linked: {
          enable: false, // No lines between raindrops
        },
        move: {
          enable: true,
          speed: 6, // Falling speed
          direction: 'bottom', // Fall downwards
          random: true,
          straight: false,
          out_mode: 'out', // Disappear when out of bounds
          bounce: false,
          attract: {
            enable: false,
          }
        }
      },
      interactivity: {
        detect_on: 'canvas',
        events: {
          onhover: {
            enable: false, // No hover effects
          },
          onclick: {
            enable: false, // No click effects
          },
          resize: true
        }
      },
      retina_detect: true
    });
  }

コメント

人気の投稿

Bloggerでは“コピー用アイコン”が出せないの?

Googleドライブの共有で浮気がバレるかもしれない・・・www

ブックマークレット