万博マニアックマップに雪を降らそう
実際の大阪・開催万博では、開催中に雪は振らなかったけど画面の中なら出来るよね。
そんな訳で、MapLibre GS JSの3D機能を駆使して、本格的な雪を降らせて見ました!
すみません、冗談です。地図は3Dだけど、雪は完全な2Dです。
雪景色にするためやったこと
style.jsonを雪景色に変更
- 何処を修正したかは同じフォルダの「osmfj_nopoi.json」と比較すれば分かります。
- 比較しなくても、このファイルをそのまま使って貰っても大丈夫です(MIT License)。
https://github.com/K-Sakanoshita/expo2025-maniacs/blob/main/tiles/osmfj_nopoi_night_snow.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は、みなさんのご参加をお待ちしています。