【Party.js】で魔法使いになってみた（基本的な使い方から〜カスタマイズまで）【JavaScript / ポートフォリオ / UX】

#　はじめに
　みなさん『ハリー・ポッター』が好きですか？
　僕は好きです。小さい頃はよく木の枝で奇妙な形をなぞって、どこの国の言語かもわからない呪文を唱えながら遊んでいました。特に光を出す「ルーモス」という魔法に憧れてて、それである日。。。

　え？なんの話かって？
　ごめんごめん、[Party.js](https://party.js.org/)を紹介しようとしていました。

　これはWebページに「**<font color="tomato">紙吹雪</font>**」や「**<font color="darkgoldenrod">星形がキラキラと爆ける<font>**」エフェクトを表現できるとても面白い**JavaScriptのライブラリー**なんです。
　ユーザーがボタンなどをクリックすると発火し、フォームの**Submitボタン**や**お気に入りボタン**に実装することで、**ページ全体が華やかになり、ユーザー体験を向上させられます。**

　どんなエフェクトなのか、さっそく見ていきましょう。
　そうですね、今の時期は冬で、冬と言えば雪ですよね。では**<font color="dodgerblue">雪の魔法使い</font>**になっていただきましょう。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="wvrKRzE" data-preview="true" data-user="toufup" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/toufup/pen/wvrKRzE">
  party.js snow</a> by Toufup (<a href="https://codepen.io/toufup">@toufup</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

　あ。。。そこのお嬢さん、歌わなくていいですよ。

　ということで本稿ではParty.jsの__基本的な使い方から、少しこだわったカスタマイズ方法まで__紹介していきます。これを使いこなせば、Web上で好きなものを好きなだけ生やせる魔法使いになれます。

　少しだけ自己紹介をさせてください。未経験からWebエンジニアへの転職を目指しプログラミングスクールの [Runteq](https://runteq.jp/) で勉強している者です。今回紹介するParty.jsは個人開発のアプリにも使われています → [K-POPコール練習アプリ | Sycall](https://sycall.app/)。よかったらぜひ使ってみてください〜！
　また、本稿は[2021 RUNTEQアドベントカレンダー](https://qiita.com/advent-calendar/2021/runteq)に収録されています。

#　こんな方にぜひ読んでほしい
1. サイトのユーザー体験を向上させたい
1. ポートフォリオの見栄えを良くしたい
1. ~~魔法使いになりたい~~

#　この記事の構成
【1、基本の使い方】：Party.jsをサクッと導入して使ってみる
【2、カスタマイズする】：色を変えたり、持続時間を変えたり、プロパティをいろいろいじってみる
【3、応用する】：さらにこだわりを！ハート型や絵文字など、好きな形にカスタマイズしてみる

#　0、インストール
cdn

```html
<script src="https://cdn.jsdelivr.net/npm/party-js@latest/bundle/party.min.js"></script>
```

npm、yarn

```shell
npm install party-js
# or
yarn add party-js
```

```JavaScript
import party from "party-js";
// or
const party = require("party-js");
```

#　1、基本の使い方
　1、任意のHTML要素にクリックイベントを設定し、ハンドラにParty.jsのメソッドを使って処理を書きます。
　例として`<button>`タグを使っていますが、`<div>`タグ、`<a>`タグももちろんOKです。

```html
<button class="btn1">confetti</button>
<button class="btn2">sparkles</button>
```

　2、デフォルトでは**`confetti`**と**`sparkles`**メソッドが使えます。
　この2つは作者がParty.jsのモジュールを上手に組み合わせてくれたプリセットです。
　confetti は紙吹雪の意味で、sparkles は輝く意味です。

　第一引数には**`HTMLElement`**、または**`MouseEvent`**のオブジェクトを、
　第二引数（省略可）にはカスタマイズの設定を書きます（この後のセクションで紹介します）

```javascript
document.querySelector(".btn1").addEventListener("click", function (e) {
    party.confetti(this);
});

document.querySelector(".btn2").addEventListener("click", function (e) {
    party.sparkles(this);
});
```

codepen で確認してみましょう
<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="zYEvgMo" data-preview="true" data-user="toufup" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/toufup/pen/zYEvgMo">
  Untitled</a> by Toufup (<a href="https://codepen.io/toufup">@toufup</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

　メソッドの第一引数に`HTMLElement`を使うのと`MouseEvent`を使うのとでは挙動が若干変わります。
　`HTMLElement`はボタン全体を中心にエフェクトが発生するのに対して、
　`MouseEvent`クリックした点を中心にエフェクトが発生します。
　ここは好みの問題なのでどちらでも構いませんが、個人的に MouseEvent に設定したほうが望ましい挙動になります。

```javascript
document.querySelector(".btn1").addEventListener("click", function (e) {
    // ボタン全体を中心にエフェクトが発生
    party.confetti(this);
});

document.querySelector(".btn2").addEventListener("click", function (e) {
    // クリックした点を中心にエフェクトが発生
    party.sparkles(e);
});
```

#　2、カスタマイズする
　`sparkles`をカスタマイズする方法を紹介していきます。`confetti`については[公式Doc](https://party.js.org/docs/ref/templates)を参照してください。まあプロパティが大体同じなので通用できると思います。
　先ほど言及したように、カスタマイズするためのオプションは sparkles や confetti の**第二引数に、オブジェクトの形で指定してあげます。**
　なお、便宜のためここでは confetti の紙屑、 sparkles の星形のことを「粒子」と呼ぶことにします。

### lifetime：粒子の持続時間
`lifetime: party.variation.range(最小持続時間[秒], 最大持続時間[秒])`

　`party.variation.range()`は指定された範囲内の時間をランダムに生成する**関数を返します。**なので、粒子の一つひとつが異なる持続時間を持ちます。
　全部同じ持続時間にしたければ、固定の数値を渡せばいいです。

```javascript
document.querySelector(".btn2").addEventListener("click", function (e) {
    party.sparkles(e,{
        // 2〜4秒持続します（粒子ごとに異なります）
        lifetime: party.variation.range(2, 4),
        // 5秒持続します
        // lifetime: 5,
    });
});
```

### count：粒子の数
`count: party.variation.range(最小個数, 最大個数)`

```javascript
document.querySelector(".btn2").addEventListener("click", function (e) {
    party.sparkles(e,{
        // 粒子の数は10〜20個（イベント発火するたびに変化します）
        count: party.variation.range(10, 20),
        // 固定で10個生成します
        // count: 5,
    });
});
```

### speed：粒子が拡散していく速度
`speed: party.variation.range(最小速度, 最大速度)`
　単位不明ですがおそらく`ピクセル/1秒` だと思います。

```javascript
document.querySelector(".btn2").addEventListener("click", function (e) {
    party.sparkles(e,{
        // 速度100〜200で拡散していきます。（粒子ごとに異なります）
        speed: party.variation.range(100, 200),
        // 固定で速度10で拡散していきます。
        // speed: 10,
    });
});
```


### size：粒子の初期の大きさ
`size: party.variation.range(最小倍率, 最大倍率)`
　単位不明ですがおそらく`ソース粒子の何倍` だと思います。
　ソース粒子の大きさはあらかじめ決まっているため、デフォルトの sparkles と confetti メソッドにおいては変更できません。

```javascript
document.querySelector(".btn2").addEventListener("click", function (e) {
    party.sparkles(e,{
        // ソース粒子の1〜3倍（粒子ごとに異なります）
        size: party.variation.range(1, 3),
        // 固定でソース粒子の10倍。
        // size: 10,
    });
});
```

### rotation：粒子の初期の角度
`rotation: () => new party.Vector(x軸, y軸, z軸)`
　x軸, y軸を変更するシーンはあまりないと思います。使い方としてはz軸をランダムに変化させるか、固定の値にするかぐらいです。（どちらにせよ粒子がぐるぐる回転し出すと角度なんて気にならないので。。。）

```javascript
document.querySelector(".btn2").addEventListener("click", function (e) {
    party.sparkles(e,{
        // 初期の角度が0~360度（粒子ごとに異なります）
        rotation: () => new party.Vector(0, 0, party.random.randomRange(0, 360))
        // 固定で90度
        // rotation: () => new party.Vector(0, 0, 90),
    });
});
```

### color：粒子の初期の色
`color: () => party.Color.fromHsl(h, s, l)`
h, s, lの値は`party.random.randomRange(最小値, 最大値)`を使って動的に変化できます。

または
`color: party.Color.fromHex(カラーコード)`（#66ccff みたいなコードのことです）

注意：粒子ごとに色を変化させたい場合は関数をreturnしてあげます。固定の値の場合メソッドの戻り値だけ渡せばOKです。

```javascript
document.querySelector(".btn2").addEventListener("click", function (e) {
    party.sparkles(e,{
        // 初期の色が緑（粒子ごとに明度が異なります）
        color: () => party.Color.fromHsl(150, 100, party.random.randomRange(50, 85))
        // 固定で90度
        // rotation: new party.Vector(0, 0, 90),
    });
});
```

#　3、応用する
## 3-1、星をハート型に変える
　魔法使いたるものは星形だけに満足してはいけません。今度はハート型の sparkles エフェクトを作ってみましょう。
　<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="qBPbVMW" data-preview="true" data-user="toufup" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/toufup/pen/qBPbVMW">
  party.js hearts</a> by Toufup (<a href="https://codepen.io/toufup">@toufup</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

　と言っても、実は公式のドキュメントにこの作り方とコードが載っているんです。["Hearts" Demo](https://party.js.org/docs/guides/custom-effects#hearts-demo)

　コピペすればすぐに使えるんですが、それだけだと今後応用できないので、少しコードを読んでみます。
　下記の部分がハート型を作るコードですが、どうやら[Document.createElementNS()](https://developer.mozilla.org/ja/docs/Web/API/Document/createElementNS)を使って SVGElement を作成しているようです。SVG は図形をコードで表現できるものです。4行目の`"M316.722,29.....なんとか`のコードがハート型を描くためのコードです。

```javascript
const heartPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
heartPath.setAttribute(
	"d",
	"M316.722,29.761c66.852,0,121.053,54.202,121.053,121.041c0,110.478-218.893,257.212-218.893,257.212S0,266.569,0,150.801 C0,67.584,54.202,29.761,121.041,29.761c40.262,0,75.827,19.745,97.841,49.976C240.899,49.506,276.47,29.761,316.722,29.761z"
);

const heartShape = document.createElementNS("http://www.w3.org/2000/svg", "svg");
heartShape.setAttribute("viewBox", "0 0 512 512");
heartShape.setAttribute("height", "20");
heartShape.setAttribute("width", "20");
heartShape.appendChild(heartPath);
```

そして出来上がった SVGElement（変数 heartShape のこと）を shapeFactory で指定します。すると粒子がハート型に変身します。

```javascript
        rendererOptions: {
		shapeFactory: heartShape,
		applyLighting: undefined,
	},
```

　ここでひとつ思ったのですが、SVGElement を描くためのコードを変えれば、もっといろんな形にできるのでは？例えば記事冒頭の雪印の図形。
　しかし、その長い長い`"M316.722,29.....なんとか`のコードは一体どうやって書くのでしょうか？

　実は [FontAwesome](https://fontawesome.com/v5.15/icons/heart?style=regular) や [MaterialDesignIcons](https://materialdesignicons.com/) などのサイトで見つけることができます。
　FontAwesome だとちょっと面倒で、一度SVGファイルをダウンロードしてからファイルのソースコードから漁ってくるか、↓
![スクリーンショット 2021-12-06 23.39.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227249/ccbce236-fa54-49e5-ad65-23f8edfe9614.png)
または開発者ツールでアイコンのコードから取ってきます。↓
![スクリーンショット 2021-12-06 23.40.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227249/b8e5d590-93cb-ac16-ece4-91ef2b55b5d0.png)

MaterialDesignIcons では `View SVG`というメニューから簡単に見ることができます。
![スクリーンショット 2021-12-06 23.44.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227249/308232ec-7e64-b717-9d07-41687a131d4e.png)
![スクリーンショット 2021-12-06 23.46.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227249/6064a799-7ab8-7a07-c2b9-5e2d7760b56e.png)
この部分を先ほどの`"M316.722,29.....なんとか`のコードに置き換えれば任意の図形にカスタマイズすることができます！！

## 3-2、絵文字もいける
みんなの大好きな絵文字ももちろん粒子として使えます！
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="RwLWXBy" data-preview="true" data-user="toufup" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/toufup/pen/RwLWXBy">
  party.js money</a> by Toufup (<a href="https://codepen.io/toufup">@toufup</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

ポイントは`document.createElement`で要素を作り絵文字を`innerText`で入れることです。

```javascript
    const moneyElement = document.createElement("span")
    moneyElement.innerText = "🥟"
//（省略）
    rendererOptions: {
            shapeFactory: gyouzaElement,
            applyLighting: undefined,
    }
```

　同じ理論で自前のPNG画像を粒子として指定することもできると思います。興味ある方はぜひ試してみてください。

## 3-3、あるいはこんなこと。。。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="YzrGoWv" data-preview="true" data-user="toufup" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/toufup/pen/YzrGoWv">
  party.js gyouza</a> by Toufup (<a href="https://codepen.io/toufup">@toufup</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

www いろいろ遊んでみてください

#　おわりに
　いかがだったでしょうか？Party.jsを上手に使えば、Webページに躍動感や華やかさをもたらすことができます。
　しかし、何でもかんでもエフェクトを出してしまうと逆に鬱陶しくなったりもするので、「ここぞ！」というところにだけ使用した方が良いかと思います。

# 参考
https://party.js.org/
https://github.com/yiliansource/party-js