mooriii's blog

article icon

アニメーションを活用してリアルタイムなカーソル同期のパフォーマンスを改善する

この記事はAtrae Advent Calendar 2024の18日目の記事です。前回は@aki90935433による「生成AIアプリ開発ツールDifyをAWS EKSに導入してみた」でした。


MiroやFigmaのようなオンラインホワイトボードツールでは他のユーザーのカーソルがリアルタイムに表示される機能が必須となっていますが、Websocketなどの技術を用いて高精度でリアルタイムな表示を実現しようとすると、パフォーマンスの懸念が出てきます。

一方、パフォーマンスを気にしすぎるとユーザー体験に影響が出てしまうことがあります。

今回はカーソルにフォーカスして、ユーザー体験をできるだけ損なわずにパフォーマンスを向上する工夫について書いていきます。

詳細はliveblocksの記事がとても参考になるのでぜひご覧ください。デモもあるのでわかりやすいです。

How to animate multiplayer cursors | Liveblocks BlogSmoothly rendering live cursors is more difficult than it sounds when real‑world conditions are taken into account—here's a quick introduction to a few different methods, plus some React snippets.
favicon of liveblocks.io
ogp of https://liveblocks.io/images/blog/how-to-animate-multiplayer-cursors.jpg

Throttleで処理を間引く

カーソルのデータを同期する際mousemoveイベントを利用しますが、マウスを動かしている間は当然高頻度でイベントが発火するので、すべてのデータをサーバーに送信すると、サーバー・クライアントともに負荷が高くなります。

Throttleで間引く前のカーソルの同期ではイベント発火ごとに処理が走るのでコンソールに表示すると高頻度でログが吐かれる

ちょっと見にくいですがGifに映っているコンソールを見てみるとかなりの頻度でログが吐かれています。

ChromeのPerformanceタブでCPUの負荷を計測してもかなり負荷がかかっていることがわかります。(画像)

Throttleの処理を入れる前のCPUの負荷が高いプロファイルの画像
(画像はカーソル以外の処理も含めたときのプロファイルです)

高頻度の処理によって負荷が上がっているので、頻度を落とすためにThrottle(同じ処理が連続する際に、一定間隔で間引く手法)を活用します。

【図解】DebounceとThrottleの概念の違いについてまとめてみた。
favicon of https://zenn.dev/tyyy/articles/debounce-throttlezenn.dev
ogp of https://res.cloudinary.com/zenn/image/upload/s--Xuz5pGuS--/c_fit%2Cg_north_west%2Cl_text:notosansjp-medium.otf_55:%25E3%2580%2590%25E5%259B%25B3%25E8%25A7%25A3%25E3%2580%2591Debounce%25E3%2581%25A8Throttle%25E3%2581%25AE%25E6%25A6%2582%25E5%25BF%25B5%25E3%2581%25AE%25E9%2581%2595%25E3%2581%2584%25E3%2581%25AB%25E3%2581%25A4%25E3%2581%2584%25E3%2581%25A6%25E3%2581%25BE%25E3%2581%25A8%25E3%2582%2581%25E3%2581%25A6%25E3%2581%25BF%25E3%2581%259F%25E3%2580%2582%2Cw_1010%2Cx_90%2Cy_100/g_south_west%2Cl_text:notosansjp-medium.otf_37:mycom%2Cx_203%2Cy_121/g_south_west%2Ch_90%2Cl_fetch:aHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL3plbm4tdXNlci11cGxvYWQvYXZhdGFyLzc3ZjE1MGI3NzIuanBlZw==%2Cr_max%2Cw_90%2Cx_87%2Cy_95/v1627283836/default/og-base-w1200-v2.png

mousemove イベントの処理をThrottleを使って間引くことで、負荷を下げることができます。

Throttleで間引いたカーソルの様子

こちらもGifに映っているコンソールを見てみるとログを吐く頻度が全然違います。

Performanceタブで負荷を計測してみてもCPUへの負荷がかなり減少していることがわかります。(画像)

Throttleの処理を入れた後のCPUの負荷が比較的下がっているプロファイルの画像

(デモで作ったアプリではahooksのuseThrottleFnを使っています)

カーソルにアニメーションをつける

Throttleを入れることで負荷を下げることはできましたが、動画を見るとわかるようにカクカクになります。

そうなるとパフォーマンスは向上したもののユーザー体験が損なわれてしまいます。

そこでカーソルにアニメーションを付けることでカクつきを軽減します。

ということでデモを用意してみました。

デモではアニメーションのON/OFFやThrottleのインターバルを調整できるようにしたので、切り替えながら体感してみてください。

ここでカーソルを動かしてみてください

アニメーションを付けるだけでカクつきが大幅に軽減されていることがわかります。

おわりに

今回はオンラインホワイトボードで他のユーザーのカーソルを表示する際の工夫について書いてみました。

リアルタイム性とパフォーマンスの両方が求められるので、こういった工夫がとても大事になってきます。

リアルタイム編集可能なホワイトボードということで、普段のフロントエンドより一層パフォーマンスに気をつけなければならないので今後も面白い技術があったら書いていこうと思います。

LGTM

宣伝

我が家の猫のLGTM画像サイトです。ぜひご自由に使ってください。

Lgtlatte - らてのLGTM画像飼い猫らてのLGTM画像を集めました
favicon of https://lgtlatte.mooriii.com/lgtlatte.mooriii.com
ogp of https://images.ctfassets.net/rd8mwctho8md/CvOcilcY3CGMuYLJPqxGL/4866b02e655a7d52c1fb19afcf9eb4c1/ogp.png
この記事をシェアするx icon
アイコン画像
Takuto Mori@_mooriii

Wevoxというサービスのフロントエンジニアをしています。趣味は猫を眺めることです🐱