deck.glとNext.jsで東京のラーメン屋ヒートマップをつくってみた!
※ちょっとずつ書いているので、その辺はおおらかな目で見てください
くそ余談(ただの日記)(お急ぎの方は読み飛ばしてください)
こんにちは。微光です。
フリーランスで Web エンジニアをしていたのですが、この度法人を立ち上げ、晴れて零細開発会社社長となりました。
会社にしたからには、やはりビッグになりたいもの。
どんどんお客様のビジネスに貢献しつつ、組織を拡大していく所存です。
それで、やはりビジネスには強みが必要ということで、何かないかなーと思っていました。
エンジニアとして働き始めて、これといって「こういうキャリアプランで!」というのはなく、なんとなく任せていただけるお仕事を一生懸命頑張っていました。
今までやってきた仕事を棚卸してみるとこんな感じでした。
- ドローンと LiDAR を活用した機械学習関連の研究(大学)(Python)
- Web 広告代理店でデータ分析(インターン)(GCP, Python, Tableau)
- GIS 系の教育系システムの開発(Python, Cesium)
- GIS 系の WebAPI の開発(Django)
- 医療系のデータ分析基盤構築および社内 Web アプリの開発(Laravel, AWS)
- GIS 系の Web アプリ開発(React, Django)
こんな感じです。
この経歴を ChatGPT の o3 に投げてみて、うちのブランドをつくってもらいました。
それがこちら
Location Intelligence Studio ― "地理空間データをビジネス価値に変える" 専門家集団
かっけぇ…
これでいきます。
ピンときた方は気軽にご相談ください
本題
というわけで、とりあえず会社の宣伝目的で何か開発して技術発信をしようということで、
東京ラーメン屋ヒートマップをつくろうと思って作りました。
deck.gl を使ってみたくて。
特別ラーメンが好きなわけではないです。(ラーメンって食べ物とは別の何かにカテゴライズされている感じしますよね)
主な仕様技術は以下になります。
- Next.js 14 (App Router)
- deck.gl の HeatmapLayer と ScatterplotLayer を利用した WebGL レンダー
- MapLibre GL + Carto の Voyager ベースマップ
- Chakra UI を用いた UI コンポーネント
- OpenStreetMap の Overpass API からの動的データ取得
完成品がこんな感じです。
主な機能としては以下のような感じです。
- マップ上で東京のラーメン店舗の分布をヒートマップで可視化し、密集エリアが一目でわかる
- スライダーでヒートマップの強度、しきい値、表示半径をリアルタイムに調整可能
- 店舗ポイントにマウスを乗せると、店舗名をポップアップで表示
- 地図のドラッグ・ズーム操作で表示範囲を変更すると自動でデータを再読み込み
- ナビゲーションコントロールで簡単に地図のズームや回転ができる
- 池袋駅のマーカーを目印として常時表示
- 表示中の店舗数を画面右下に常時表示
- データ読み込み中にはローディングメッセージを表示し、エラー時にはエラーメッセージを出力
- PC・スマホ・タブレットなどマルチデバイス対応で快適に操作
という構成で「東京ラーメン屋ヒートマップ」を手軽に作る手順をご紹介します。
Github に公開しているので、解説なんていらねーよって人はこちらを見てください。
サービスはこちらで公開しています!
1. 準備と環境構築
- Node.js ≥ 16
- yarn または npm
# プロジェクト作成
npx create-next-app ramen-heatmap
cd ramen-heatmap
# 依存パッケージのインストール
yarn add deck.gl @deck.gl/react @deck.gl/aggregation-layers react-map-gl maplibre-gl @chakra-ui/react @chakra-ui/next-js framer-motion
2. データの取得
ラーメン店のデータは、OpenStreetMap の Overpass API を使用して、現在の地図範囲内の店舗情報を動的に取得します。
ViewModel 内で地図ビューからバウンディングボックスを計算し、UseCase を通じて Overpass API を呼び出します。
3. Next.js プロジェクトのセットアップ
App Router を利用し、app/page.tsx
にて RamenHeatmap
コンポーネントを呼び出します。
// app/page.tsx
import { RamenHeatmap } from "@/src/presentation/components/RamenHeatmap/RamenHeatmap";
export default function Page() {
return <RamenHeatmap />;
}
-
RamenHeatmap
は地図表示とヒートマップ設定パネルを内包するプレゼンテーションコンポーネントです。
4. 実装ポイント
-
HeatmapLayer
とScatterplotLayer
を組み合わせた WebGL レンダリング -
HeatmapSettingsPanel
による強度(intensity)、しきい値(threshold)、半径(radius)のスライダー操作とデバウンス処理 -
useRamenHeatmapViewModel
で地図のズーム・パンに応じた Overpass API の動的データ取得 - MapLibre GL + Carto Voyager スタイルのベースマップ利用
- モバイルデバイス含むマルチデバイス対応
5. 公開とデプロイ
- Vercel や Netlify にワンクリックでデプロイ可能
- 環境変数の設定は不要
6.まとめ & 次のステップ
-
まとめ
- deck.gl + Next.js で手軽にヒートマップが描画できる
- WebGL を活用し、高速かつインタラクティブな地図表現が可能
-
次のステップ案
- ラーメン屋のカテゴリ別フィルタリング
- 時間帯や曜日ごとのヒートマップ切り替え
- クラスタリング表示やツールチップの追加
🍜 もし GIS や地図関連のフロントエンド開発に興味がある方は、ぜひお気軽にご連絡ください!
エンジニアリングチームで一緒に新しい地図体験を作り出しましょう。
Discussion