Rakugaki In The Sky
by reu · 2026/4/4
お絵描き×空飛ばし機能の実装メモ 俺のブログ(ファミマには売ってない) に「お絵描きして空に飛ばす」機能を追加した話。 背景に時刻と天気に連動した空の canvas アニメーションがあるんだけど、そこにユーザーが描いた絵を雲と一緒に流せるようにした。 ↑こんなの どんな機能? 1. スタートメニューから を起動するとお絵描きウィンドウが開く 2. ペンと消しゴムで自由に描く 3. 「☁️ 空に飛ばす」ボタンを押すと、描いた絵がシュッと空に飛んでいく 4. 飛ばした絵は背景の空に合流して、雲と同じレイヤーで左から右にふわふわ流れ続ける 5. 何度でも飛ばせるし、過去に飛ばした絵も全部流れてる 6. ページをリロードすると消える。儚い モバイルは最大5個、PCは最大15個の落書き飛ばせるよん 落書きしてみてね 以下は込み入った話 アーキテクチャ 要はお絵描き側と空の描画側を React Context でつないでるだけ。意外とシンプル。 Context: お絵描きデータの橋渡し サイトにはもともと天気オーバーライド用の があったので、同じパターンで を作った。 (このノリで機能盛っていくとContextすごいことになりそうな気がする) で配列を持って、 で追加するだけ。永続化なし、セッション限り。 layout.tsx で をアプリ全体に被せてる。 お絵描きウィンドウ ウィンドウ登録 サイトのウィンドウシステムは に定義を追加するだけで動く。 windowの管理を一元化しててよかった〜 描画の仕組み 320×240px の HTML Canvas に Pointer Events で線を引く方式。 消しゴムは を使って「透明に戻す」方式。背景が白じゃなくて透明になるので、空に飛ばした時に背景が透けて見えるのがポイント。 座標変換は表示サイズと canvas の内部解像度のズレを吸収してる: モバイルでは + で安定させてる。 飛び立ちアニメーション これ一番雑なのでそのうち直すぞ ボタンを押した瞬間、canvas の上にスナップショット画像を重ねて CSS アニメーションで飛ばす: Tailwind の で として登録。800ms の で上に縮みながら消えていく。 空側: SkyCanvas へのドリフト描画 データの流れ DriftingDrawing 型 → の変換は + で1回だけ。以降のフレームでは で高速に描画。 同期ロジック prop が変わるたびに、まだ にない id のものだけ新規追加する: モバイルは最大5個、PCは最大15個。超えたら古いのを で除去。 雲の直後、天気パーティクルの前に配置。雨や雪は絵の上に降る形になる。 ドリフト描画関数 雲と同じで、右端まで行ったら左端に戻ってまた流れてくる。速度と透明度はランダムなので、絵ごとに違う「浮遊感」が出る。 設計で意識したこと 描画パフォーマンス - → の変換は初回1回のみ。 は GPU アクセラレーションが効くので毎フレーム呼んでも軽い - 320×240 の PNG は 10〜50KB 程度。メモリの心配なし - 上限を設けて古いのを自動削除 消しゴム = 透明 で消すことで、飛ばした時に背景の空が透けて見える。白で塗りつぶす方式だと空に白い四角が浮くことになるので、これが正解。 セッション限り あえて永続化しない選択。気軽に描いて飛ばす「遊び」であって、作品を残す場所じゃないという割り切り。useState だけで完結するのでコードも簡素。
