はじめに
数十万件、数百万件規模の位置情報データを地図上に可視化しようとして、ブラウザが固まってしまった経験はありませんか。SVGやCanvas 2Dベースの地図ライブラリでは、点の数が増えるたびに描画がどんどん重くなり、フィルタやアニメーションを加えると一気に操作性が悪化してしまいます。
そんな悩みを解決してくれるのが、今回紹介するdeck.glです。GPUの力を最大限に活用することで、大規模データセットでもスムーズな可視化を実現してくれるライブラリで、筆者もダッシュボードのヒートマップ表示で導入してから、パフォーマンスの心配をほとんどしなくなりました。
deck.glとは
deck.glは、WebGL2をベースにした大規模データ可視化フレームワークです。もともとUberが社内の位置情報分析ツールとして開発したもので、現在はvis.glプロジェクトの一部としてOSS化されています。GitHub上で14,000以上のスターを獲得しており、地理空間データ可視化の分野で広く使われています。
主な特徴
- GPUによる高速レンダリング - WebGLを直接活用し、数百万件規模のデータポイントもスムーズに描画できます
- レイヤーを組み合わせる設計 -
ScatterplotLayerやHexagonLayerなど豊富なレイヤーを組み合わせて、複雑な可視化を宣言的に構築できます - 各種地図との連携 - Mapbox、MapLibre、Google Maps、ArcGISなどベースマップを柔軟に選択できます
- Reactとの親和性 -
@deck.gl/reactにより、Reactコンポーネントとして自然に組み込めます - 高精度な座標計算 - GPU上で64bit浮動小数点をエミュレートし、広域から詳細まで精度を保った描画が可能です
インストール
npmまたはyarnで導入します。
# npmの場合
npm install deck.gl maplibre-gl react-map-gl
# yarnの場合
yarn add deck.gl maplibre-gl react-map-gl
Reactを使わずコアライブラリのみで使いたい場合は、@deck.gl/coreや@deck.gl/layersのように必要なパッケージだけを個別にインストールすることもできます。
基本的な使い方
まずは、シンプルな散布図レイヤーを地図上に表示してみましょう。React環境での実装例です。
import React from "react";
import DeckGL from "@deck.gl/react";
import { ScatterplotLayer } from "@deck.gl/layers";
import Map from "react-map-gl/maplibre";
import "maplibre-gl/dist/maplibre-gl.css";
type PointData = {
position: [number, number];
size: number;
};
const data: PointData[] = [
{ position: [139.767, 35.681], size: 100 }, // 東京駅
{ position: [135.496, 34.702], size: 80 }, // 大阪駅
{ position: [136.881, 35.171], size: 60 }, // 名古屋駅
];
const layer = new ScatterplotLayer<PointData>({
id: "scatterplot-layer",
data,
getPosition: (d) => d.position,
getRadius: (d) => d.size,
getFillColor: [30, 144, 255, 180],
radiusScale: 30,
pickable: true,
});
const INITIAL_VIEW_STATE = {
longitude: 137.5,
latitude: 35.0,
zoom: 5,
pitch: 0,
bearing: 0,
};
export function DeckMap() {
return (
<DeckGL
initialViewState={INITIAL_VIEW_STATE}
controller
layers={[layer]}
style={{ width: "100%", height: "500px", position: "relative" }}
>
<Map
mapStyle="https://demotiles.maplibre.org/style.json"
reuseMaps
/>
</DeckGL>
);
}
layersプロパティに渡すレイヤーの配列を変更するだけで、表示内容を切り替えられます。pickable: trueを設定すれば、onClickやonHoverイベントで各データポイントの情報を取得することも可能です。
実践的なユースケース
実務では、大量の位置データを密度に応じて可視化したい場面がよくあります。ここではHexagonLayerを使い、六角形ビンで集計した密度マップを作る例を紹介します。
import { HexagonLayer } from "@deck.gl/aggregation-layers";
type LocationPoint = {
longitude: number;
latitude: number;
};
function createDensityLayer(points: LocationPoint[]) {
return new HexagonLayer<LocationPoint>({
id: "hexagon-layer",
data: points,
getPosition: (d) => [d.longitude, d.latitude],
radius: 1000, // 六角形の半径(メートル)
elevationScale: 4,
extruded: true,
pickable: true,
colorRange: [
[255, 255, 178],
[254, 217, 118],
[254, 178, 76],
[253, 141, 60],
[240, 59, 32],
[189, 0, 38],
],
});
}
このように、来店客の位置ログや配送実績のGPSデータなどを渡すだけで、密集エリアを立体的なヒートマップとして表現できます。3Dの高さ情報が加わることで、単純な色分けよりも直感的に密度の差を把握できるのも大きなメリットです。
他にも、経路データを可視化するArcLayerやGeoJSON形式の行政区域を描画するGeoJsonLayerなど、用途に応じたレイヤーが揃っているため、物流の配送ルート分析や不動産データの地域別集計といった場面でも活躍します。
まとめ
deck.glは、GPUを活用した高速レンダリングと、レイヤーを組み合わせる柔軟な設計により、大規模な地理空間データの可視化を得意とするライブラリです。ScatterplotLayerのようなシンプルな点描画から、HexagonLayerを使った密度分析まで、宣言的なAPIで段階的にステップアップしていけるのも魅力です。
大量データの地図可視化でパフォーマンスに悩んでいる方は、まずは公式ドキュメントのExamplesページで気になるレイヤーを試してみて、自分のデータに置き換えて動かしてみることをおすすめします。