0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

万博マニアックマップに雪景色を追加してみる

Posted at

万博マニアックマップに雪を降らそう

実際の大阪・開催万博では、開催中に雪は振らなかったけど画面の中なら出来るよね。
そんな訳で、MapLibre GS JSの3D機能を駆使して、本格的な雪を降らせて見ました!

すみません、冗談です。地図は3Dだけど、雪は完全な2Dです。

雪景色にするためやったこと

style.jsonを雪景色に変更

では、雪を降らそう

  • 万博マニアックマップのindex.htmlに以下のcanvasを追加します。
  • 当たり前ですが、canvasで雪を描いて動かせば、MapLibreと無関係に動きます。
index.html
<main id="top-pane">
    <div id="mapid"></div>
    <canvas id="snow"></canvas>
</main>
  • 以下が雪の初期化と描画処理です。昔の8ビットゲーム機みたいなシンプルなコード。
  • 雪の属性(大きさや速度、透明度)を初期化時に設定して、あとは延々と繰り返し。
  • あ。requestAnimationFrameはディスプレイのリフレッシュレート依存なので、端末によって雪の速度が違うかも。直さねば。
winlib.js
/* 雪Canvas 初期化 */
const canvas = document.getElementById('snow');
const ctx = canvas.getContext('2d');

function resize() {
    const dpr = window.devicePixelRatio || 1;
    canvas.width = Math.floor(window.innerWidth * dpr);
    canvas.height = Math.floor(window.innerHeight * dpr);
    canvas.style.width = window.innerWidth + 'px';
    canvas.style.height = window.innerHeight + 'px';
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
window.addEventListener('resize', resize);
resize();

/* 雪パーティクル */
const FLAKE_COUNT = 200;
const flakes = Array.from({ length: FLAKE_COUNT }, () => ({
    x: Math.random() * window.innerWidth,
    y: Math.random() * window.innerHeight,
    r: 1 + Math.random() * 2.5,     // 半径
    vx: -0.4 + Math.random() * 0.8, // 横風
    vy: 0.8 + Math.random() * 1.8,  // 落下速度
    a: 0.3 + Math.random() * 0.5    // 透明度
}));

function drawSnow() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    for (const f of flakes) {
        f.x += f.vx;
        f.y += f.vy;

        if (f.y > window.innerHeight + 10) {
            f.y = -10;
            f.x = Math.random() * window.innerWidth;
        }
        if (f.x < -10) f.x = window.innerWidth + 10;
        if (f.x > window.innerWidth + 10) f.x = -10;

        ctx.globalAlpha = f.a;
        ctx.beginPath();
        ctx.arc(f.x, f.y, f.r, 0, Math.PI * 2);
        ctx.fillStyle = '#ffffff';
        ctx.fill();
    }

    ctx.globalAlpha = 1;
    winCont.snowAnimId = requestAnimationFrame(drawSnow);
}
drawSnow();

何が言いたかったのか

  • 人間って、案外いい加減な生き物なので、2Dの雪でもそれっぽく見えるのかなと。
  • 真面目に3D演算しても良いけど、雰囲気を味わうぐらいなら2Dでも丁度良いかな。
  • CPUやGPU負担も高くないしね。まぁ、アイデア出したのChatGPTだけど(苦笑)

参考リンク

  • 万博マニアックマップで遊ぶにはこちらから。

  • 万博マニアックマップのソースコードがこちらからダウンロードできます。

  • Discord OpenStreetMap Japanは、みなさんのご参加をお待ちしています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?