ブラウザのタブ間でのリアルタイム通信を p5.js で 1つずつ試す： Web Storage API の localStorage【完走賞ゲット-4】

 :::note info
※ [Qiita の完走賞をゲットするための条件は「単一／複数のカレンダーに投稿した記事が合計25」です](https://twitter.com/Qiita/status/1593441648796524545)
:::

この記事は、「[完走賞ゲットのため小ネタ 25記事を投稿しようとチャレンジ v2 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/youtoy)」の 4日目の記事です。

## 今回の内容
今回の記事の内容は、2年以上前に以下の記事で紹介していた内容に関する話です。

●ブラウザのタブ間でのリアルタイム通信を行う 4つの方法【概要編】 #JavaScript - Qiita
　https://qiita.com/youtoy/items/b202209d0eb36bad830f

上記の記事の続きを、昨日書いた以下の記事で少し扱ったのですが、今回の記事はさらにその続きという位置づけです。

 ●ブラウザのタブ間でのリアルタイム通信を p5.js で 1つずつ試す： Broadcast Channel API【完走賞ゲット-3】 - Qiita
　https://qiita.com/youtoy/items/34520f8357cd6fe6aabd

## Web Storage API の localStorage
今回使うのは、Web Storage API の localStorage です。

### Web Storage API
Web Storage API についても軽く触れておきます。

Web Storage API は、以下の MDN のページにも書かれているように、ブラウザーでキーと値のペアを保存できる仕組みです。

●ウェブストレージ API - Web API | MDN
　https://developer.mozilla.org/ja/docs/Web/API/Web_Storage_API

そして、その仕組みには sessionStorage と localStorage の 2 種類があります。詳細は、MDN に書かれた以下などの説明をご参照ください。

![2つの仕組み](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/f7c31f4e-49f0-fe4a-6fb6-06fc8694ae1f.png)

### localStorage の仕様
今回の記事では 上で書いた 2つの仕組みのうち、以下の MDN のページにも登場している「localStorage」を扱います。

- [ウェブストレージ API の使用 - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API)
- [Window: localStorage プロパティ - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Window/localStorage)

上記のページの中に書かれているように、以下の処理で「読み書き、削除」が行えるようです。
![MDNのページ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/18298204-d4c8-eacd-feed-ff6db829bac0.png)

### localStorage を p5.js で使う
それでは、p5.js の中でこの localStorage を使ってみます。

どんな実装で試したか、まずは動作結果を見ていただくことにします。以下では、シンプルに、mouseX のみを使って、横方向の動きのみシンクロさせています。

<iframe width="560" height="315" src="https://www.youtube.com/embed/cK1z3jnLplI?si=aO2VtFPyiyutNmwW" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

#### 実装内容
それでは、送信側と受信側の、それぞれの実装内容を掲載します（※ 以下の例に関しては、実装と動作確認を p5.js Web Editor上で行っています
）。

以下が送信側です。mouseMoved() のイベントが発生した際、mouseX を使った円の描画を行いつつ、その mouseX の値を localStorage に保存しています。

```javascript:送信側
function setup() {
  createCanvas(400, 200);
  background(220);
}

function mouseMoved() {
  const x = mouseX;
  console.log(x);
  localStorage.setItem("mouseX", x);

  background(220, 255 * 0.5);
  circle(mouseX, height / 2, 30);
}
```

そして以下が受信側です。
localStorage に変更があった場合に発生する storage イベントを、addEventListener() で登録しています。さらに、キーの値が、送信側で設定していた `mouseX` だった場合に、変更後の値を取り出して円の描画に利用します。

```javascript:送信側
function setup() {
  createCanvas(400, 200);
  background(120);
  noStroke();
  fill(100, 150, 220);

  window.addEventListener("storage", receiveMouseX);
}

function receiveMouseX(event) {
  if (event.key === "mouseX") {
    let receivedMouseX = event.newValue;
    console.log(receivedMouseX);

    background(120);
    circle(receivedMouseX, height / 2, 50);
  }
}
```

#### オブジェクトを利用する場合
今回使った localStorage を使ったデータの送受信で、オブジェクトを扱いたい場合は、[MDN のページ](https://developer.mozilla.org/ja/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%AB%E5%80%A4%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B)でも説明されていますが、以下のように `JSON.stringify()` 、 `JSON.parse()` を使用する必要があるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/f8f26720-8e6f-02bf-1b6e-22dc400b04c2.png)

## おわりに
ブラウザのタブ間でのリアルタイム通信を実現する方法に関して、この前は「Broadcast Channel API」を使いましたが、今回は「localStorage」を使った方法を用い、データの送受信を行うことができました。

今後、「Broadcast Channel API」「localStorage」を使った方法も試してみて、実装内容の比較などを行えればと思います。