MapLibre入門

MapLibreは、美しいベクタータイル地図を表示できるオープンソースライブラリです。

MapLibre入門【オープンソースのベクタータイル地図】

この記事では、MapLibreの基礎から実践的な使い方まで解説します。

MapLibreとは

概要

MapLibre GL JSは、Mapbox GL JSからフォークされたオープンソースの地図ライブラリです。

【特徴】
・ベクタータイル対応
・美しい地図表現
・高速な描画
・完全にオープンソース
・3D表示対応

Leafletとの違い

項目 MapLibre Leaflet
タイル形式 ベクター ラスター
描画速度 高速 普通
スタイル 柔軟 制限あり
3D対応 ×
ファイルサイズ 大きい 小さい

ベクタータイルのメリット

メリット

  • スムーズなズーム
  • 動的なスタイル変更
  • 高速な描画
  • 軽量なデータ
  • 回転・傾斜表示

セットアップ

CDNを使用

html
<!DOCTYPE html>
<html>
<head>
    <title>MapLibre Map</title>
    <script src="https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.js"></script>
    <link href="https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.css" rel="stylesheet" />
    <style>
        body { margin: 0; padding: 0; }
        #map { width: 100%; height: 100vh; }
    </style>
</head>
<body>
    <div id="map"></div>
    <script src="map.js"></script>
</body>
</html>

npm/yarnを使用

bash
npm install maplibre-gl

javascript
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';

const map = new maplibregl.Map({
    container: 'map',
    style: 'https://demotiles.maplibre.org/style.json',
    center: [139.7671, 35.6812],
    zoom: 13
});

基本操作

地図の作成

javascript
// 基本的な地図作成
var map = new maplibregl.Map({
    container: 'map',                // コンテナID
    style: 'style.json',             // スタイルJSON
    center: [139.7671, 35.6812],     // 中心座標 [lng, lat]
    zoom: 13,                        // ズームレベル
    pitch: 0,                        // 傾き
    bearing: 0                       // 回転
});

地理院タイルの利用

javascript
var map = new maplibregl.Map({
    container: 'map',
    style: {
        version: 8,
        sources: {
            'gsi-std': {
                type: 'raster',
                tiles: [
                    'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png'
                ],
                tileSize: 256,
                attribution: '国土地理院'
            }
        },
        layers: [{
            id: 'gsi-std-layer',
            type: 'raster',
            source: 'gsi-std'
        }]
    },
    center: [139.7671, 35.6812],
    zoom: 13
});

ナビゲーションコントロール

javascript
// ズームコントロール
map.addControl(new maplibregl.NavigationControl());

// 位置情報コントロール
map.addControl(new maplibregl.GeolocateControl({
    positionOptions: {
        enableHighAccuracy: true
    },
    trackUserLocation: true
}));

// スケールバー
map.addControl(new maplibregl.ScaleControl({
    maxWidth: 200,
    unit: 'metric'
}));

// フルスクリーン
map.addControl(new maplibregl.FullscreenControl());

地図の操作

javascript
// 移動
map.flyTo({
    center: [139.7671, 35.6812],
    zoom: 15,
    pitch: 45,
    bearing: 30
});

// ジャンプ(アニメーションなし)
map.jumpTo({
    center: [139.7671, 35.6812],
    zoom: 15
});

// 範囲にフィット
map.fitBounds([
    [139.70, 35.65],  // 南西
    [139.80, 35.70]   // 北東
]);

スタイルのカスタマイズ

スタイルJSON

json
{
    "version": 8,
    "name": "Custom Style",
    "sources": {
        "osm": {
            "type": "raster",
            "tiles": ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
            "tileSize": 256
        }
    },
    "layers": [
        {
            "id": "osm-layer",
            "type": "raster",
            "source": "osm"
        }
    ]
}

動的なスタイル変更

javascript
// レイヤーの追加
map.on('load', function() {
    // ソースを追加
    map.addSource('my-data', {
        type: 'geojson',
        data: 'data.geojson'
    });

    // レイヤーを追加
    map.addLayer({
        id: 'my-layer',
        type: 'circle',
        source: 'my-data',
        paint: {
            'circle-radius': 10,
            'circle-color': '#ff0000'
        }
    });
});

// レイヤーのスタイル変更
map.setPaintProperty('my-layer', 'circle-color', '#0000ff');

// レイヤーの表示/非表示
map.setLayoutProperty('my-layer', 'visibility', 'none');
map.setLayoutProperty('my-layer', 'visibility', 'visible');

フィルタリング

javascript
// フィルターを設定
map.setFilter('my-layer', ['==', 'type', 'office']);

// 複合条件
map.setFilter('my-layer', [
    'all',
    ['==', 'type', 'office'],
    ['>=', 'floor', 10]
]);

データソースの追加

GeoJSONソース

javascript
map.addSource('points', {
    type: 'geojson',
    data: {
        type: 'FeatureCollection',
        features: [
            {
                type: 'Feature',
                geometry: {
                    type: 'Point',
                    coordinates: [139.7671, 35.6812]
                },
                properties: {
                    name: '東京駅'
                }
            }
        ]
    }
});

map.addLayer({
    id: 'points-layer',
    type: 'circle',
    source: 'points',
    paint: {
        'circle-radius': 8,
        'circle-color': '#007cbf'
    }
});

マーカーの追加

javascript
// マーカーを作成
var marker = new maplibregl.Marker()
    .setLngLat([139.7671, 35.6812])
    .addTo(map);

// ポップアップ付きマーカー
var popup = new maplibregl.Popup({ offset: 25 })
    .setText('東京駅');

var markerWithPopup = new maplibregl.Marker()
    .setLngLat([139.7671, 35.6812])
    .setPopup(popup)
    .addTo(map);

カスタムマーカー

javascript
// HTML要素でカスタムマーカー
var el = document.createElement('div');
el.className = 'custom-marker';
el.style.backgroundImage = 'url(marker.png)';
el.style.width = '32px';
el.style.height = '32px';

new maplibregl.Marker(el)
    .setLngLat([139.7671, 35.6812])
    .addTo(map);

3D表示

地形の3D表示

javascript
var map = new maplibregl.Map({
    container: 'map',
    style: {
        version: 8,
        sources: {
            'terrain': {
                type: 'raster-dem',
                url: 'terrain-source-url'
            },
            'satellite': {
                type: 'raster',
                tiles: ['satellite-tiles-url/{z}/{x}/{y}.jpg'],
                tileSize: 256
            }
        },
        terrain: {
            source: 'terrain',
            exaggeration: 1.5
        },
        layers: [
            {
                id: 'satellite-layer',
                type: 'raster',
                source: 'satellite'
            }
        ]
    },
    center: [138.7274, 35.3606],  // 富士山
    zoom: 12,
    pitch: 60
});

建物の3D表示

javascript
map.addLayer({
    id: '3d-buildings',
    source: 'composite',
    'source-layer': 'building',
    type: 'fill-extrusion',
    minzoom: 15,
    paint: {
        'fill-extrusion-color': '#aaa',
        'fill-extrusion-height': ['get', 'height'],
        'fill-extrusion-base': ['get', 'min_height'],
        'fill-extrusion-opacity': 0.6
    }
});

カメラ操作

javascript
// 3D視点で移動
map.flyTo({
    center: [139.7671, 35.6812],
    zoom: 16,
    pitch: 60,
    bearing: 45,
    duration: 2000
});

// アニメーション
function rotateCamera() {
    map.rotateTo(map.getBearing() + 1, { duration: 100 });
    requestAnimationFrame(rotateCamera);
}
rotateCamera();

実践活用

イベント処理

javascript
// クリックイベント
map.on('click', function(e) {
    console.log('クリック位置:', e.lngLat);

    new maplibregl.Popup()
        .setLngLat(e.lngLat)
        .setHTML('<p>クリックされました</p>')
        .addTo(map);
});

// レイヤーのクリック
map.on('click', 'my-layer', function(e) {
    var feature = e.features[0];
    new maplibregl.Popup()
        .setLngLat(e.lngLat)
        .setHTML(feature.properties.name)
        .addTo(map);
});

// ホバー効果
map.on('mouseenter', 'my-layer', function() {
    map.getCanvas().style.cursor = 'pointer';
});

map.on('mouseleave', 'my-layer', function() {
    map.getCanvas().style.cursor = '';
});

画像のエクスポート

javascript
// 地図を画像として取得
function exportMap() {
    var canvas = map.getCanvas();
    var dataURL = canvas.toDataURL('image/png');

    var link = document.createElement('a');
    link.download = 'map.png';
    link.href = dataURL;
    link.click();
}

レスポンシブ対応

javascript
// ウィンドウリサイズ時に地図をリサイズ
window.addEventListener('resize', function() {
    map.resize();
});

まとめ

MapLibreの強み

特徴

  • ベクタータイル対応
  • 美しい地図表現
  • 3D表示対応
  • 完全にオープンソース

使い分け

MapLibreを選ぶ場合

  • 美しい地図が必要
  • 3D表示が必要
  • 動的なスタイル変更が必要

Leafletを選ぶ場合

  • シンプルな地図表示
  • 軽量さを重視
  • 既存プラグインを活用

関連記事

お問い合わせ

MapLibreを使ったWebGIS開発についてのご相談は、お気軽にお問い合わせください。

  • WebGIS開発相談
  • 3D地図構築支援
  • カスタマイズ開発

お問い合わせはこちら

最終更新: 2025年1月