パントレ開発部

【OpenLayers入門】地図を表示する方法と基本的な使い方

Map

はじめに

 OpenLayers とは、ブラウザでマップデータを表示する、JavaScript のオープンソースライブラリです。Web サイト上にマップをカスタマイズして埋め込む場合、Google Maps だと料金体系や著作権が問題となってきます。この問題は、OpenLayers とオープンデータのマップを組み合わせることで解決することが出来ます。

 他のマップライブラリとして Leaflet も広く知られていますが、Leaflet はプラグインが豊富でソースコードがシンプルな反面、日付変更線を跨ぐ図形の描画に問題点があったり、ベクトルタイルが使えなかったり、投影法が Web メルカトルから変更できなかったりします。そういった問題点を気にされる方には、OpenLayers は一つの選択肢になるかと思います。

 なお、OpenLayers や Leaflet の他に、MapLibre もおすすめです。これらのライブラリの比較について、私見を以下の記事にまとめています。

 

OpenLayers の導入方法

 まず HTML ファイルを作成して、OpenLayers の JavaScript と CSS を読み込みます。公式サイトによると、本番環境で用いる場合は、自分のサーバーにダウンロードしておくことを推奨しているみたいです。

<script src="https://cdn.jsdelivr.net/npm/ol@v10.4.0/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.4.0/ol.css">

 次に、マップを表示させるエリアを div タグで定義します。z-index はサイトのデザインに応じて設定してください。

<div id='mapcontainer' style='width:100%; height:300px; z-index:0;'></div>

 JavaScriptで OpenLayers のマップオブジェクトを生成するには、以下のように記載します。

const map = new ol.Map({ ... });

 上記の…にあたる部分に、idを使った<div>要素との紐づけ、マップレイヤーの追加、表示範囲の設定を記載すれば、埋め込みマップが表示されます。minZoom と maxZoom で、マップの最小ズームレベルと最大ズームレベルを制限できます。

const map = new ol.Map({
    //idを使った<div>要素との紐づけ
    target: 'mapcontainer',  
     //マップレイヤーの追加
    layers: [
       new ol.layer.Tile({
            //OpenStreetMap の読み込み
            source: new ol.source.OSM() 
        })
    ],
    //表示範囲の設定
    view: new ol.View({ 
        center: ol.proj.fromLonLat([142.14, 43.65]),  
        zoom: 6,
        minZoom: 0,
        maxZoom: 18
    })
});

 全体のソースコードと実装例は以下の通りです。

<!DOCTYPE html>
<html>
<head>
<title>htmlMap</title>
<meta http-equiv='content-type' charset='utf-8'>
<meta name='viewport' content='width=device-width'>
</head>
<body>
<!-- 埋め込みマップのdivタグ。マップサイズはwidth(幅)とheight(高さ)で決まる -->
<div id='mapcontainer' style='width:100%; height:300px; z-index:0;'></div>
<!-- 以下OpenLayersのJavaScriptとCSS -->
<script src="https://cdn.jsdelivr.net/npm/ol@v10.4.0/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.4.0/ol.css">

<script>
function init_map() {
    const map = new ol.Map({
        //idを使った<div>要素との紐づけ
        target: 'mapcontainer',  
         //マップレイヤーの追加
        layers: [
           new ol.layer.Tile({
                //OpenStreetMap の読み込み
                source: new ol.source.OSM() 
            })
        ],
        //表示範囲の設定
        view: new ol.View({ 
            center: ol.proj.fromLonLat([142.14, 43.65]),  
            zoom: 6,
            minZoom: 0,
            maxZoom: 18
        })
    });
}

//ダウンロード時に初期化する
window.addEventListener('DOMContentLoaded', init_map());

</script>
</body>
</html>

実装例

 

マップを回転させない方法

 OpenLayers はデフォルトで、スマホやタブレットであればピンチで回転、パソコンであれば、Shift+Alt+ドラッグで回転できます。しかし、回転できてしまうと操作性が落ちてしまう場合もあるので、以下マップを回転させない方法について説明します。

 マップの回転に関するデフォルトの設定を変更するためには、以下のように interaction をループで回して、マップの回転に関するもののみ削除するようにします。古いバージョンと記述がことなるので注意してください。

const map = new ol.Map({
    target: 'mapcontainer',
    layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM()
        })
    ],
    view: new ol.View({
        center: ol.proj.fromLonLat([142.14, 43.65]),
        zoom: 6
    }),
});

map.getInteractions().forEach(function(interaction) {
    if (interaction instanceof ol.interaction.DragRotate || interaction instanceof ol.interaction.PinchRotate) {
        map.removeInteraction(interaction);
    }
});

実装例



 また上記を応用して、interaction を空の配列にしてしまえば、マップを完全に固定して画像のように表示させることができます。ズームコントロールも削除して非表示にします。

const map = new ol.Map({
    target: 'mapcontainer',
    layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM()
        })
    ],
    view: new ol.View({
        center: ol.proj.fromLonLat([142.14, 43.65]),
        zoom: 6
    }),
    interactions: []
});

map.getControls().forEach(function(control) {
    if (control instanceof ol.control.Zoom) {
        map.removeControl(control);
    }
});

実装例

 

マーカーの配置

 OpenLayers でマーカーを配置するには、座標情報の Feature と、見た目の情報の Style を定義して、レイヤーに追加することで、地図上に表示させます。

 まず、マーカーの座標情報を持つ ol.Feature を定義します。

const markerFeature = new ol.Feature({
    geometry: new ol.geom.Point(ol.proj.fromLonLat([142.14, 43.65])) //[経度, 緯度]
});

次に、マーカーの見た目を管理する ol.style.Style を定義します。

const markerStyle = new ol.style.Style({
    image: new ol.style.Icon({
        anchor: [0.5, 46],        //アンカーの位置
        anchorXUnits: 'fraction', //アンカーの位置の単位(X軸)
        anchorYUnits: 'pixels',   //アンカーの位置の単位(Y軸)
        src: '画像の URL'
    })
});

 これらをレイヤーに追加します。ここで、 ol.source.Vector は Feature 一覧をまとめて管理するオブジェクトになっています。

const markerLayer = new ol.layer.Vector({
    source: new ol.source.Vector({
        features: [markerFeature]
    }),
    style: markerStyle
});

 最後に addLayer() でマップにレイヤーを追加すれば完成です。

map.addLayer(markerLayer);

 全体のソースコードと実装例は以下の通りです。

<!DOCTYPE html>
<html>
<head>
<title>htmlMap</title>
<meta http-equiv='content-type' charset='utf-8'>
<meta name='viewport' content='width=device-width'>
</head>
<body>
<!-- 埋め込みマップのdivタグ。マップサイズはwidth(幅)とheight(高さ)で決まる -->
<div id='mapcontainer' style='width:100%; height:300px; z-index:0;'></div>
<!-- 以下OpenLayersのJavaScriptとCSS -->
<script src="https://cdn.jsdelivr.net/npm/ol@v10.4.0/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.4.0/ol.css">

<script>
function init_map() {
    const map = new ol.Map({
        target: 'mapcontainer',  
        layers: [
           new ol.layer.Tile({
                source: new ol.source.OSM() 
            })
        ],
        view: new ol.View({ 
            center: ol.proj.fromLonLat([142.14, 43.65]),  
            zoom: 6,
            minZoom: 0,
            maxZoom: 18
        })
    });
    
    const markerFeature = new ol.Feature({
        geometry: new ol.geom.Point(ol.proj.fromLonLat([142.14, 43.65])) //[経度, 緯度]
    });

    const markerStyle = new ol.style.Style({
        image: new ol.style.Icon({
            anchor: [0.5, 46],        //アンカーの位置
            anchorXUnits: 'fraction', //アンカーの位置の単位(X軸)
            anchorYUnits: 'pixels',   //アンカーの位置の単位(Y軸)
            src: '画像のURL'
        })
    });

    const markerLayer = new ol.layer.Vector({
        source: new ol.source.Vector({
            features: [markerFeature]
        }),
        style: markerStyle
    });

    map.addLayer(markerLayer);
}

//ダウンロード時に初期化する
window.addEventListener('DOMContentLoaded', init_map());

</script>
</body>
</html>

実装例

 

ラインを追加する

 OpenLayers でラインを描画するには、マーカー同様に、座標情報の Feature と、見た目の情報の Style を定義して、レイヤーに追加することで、地図上に表示させます。

 まず、ラインの座標情報を持つ ol.Feature を定義します。ここで、経緯度 (EPSG:4326) を保存した配列データを、Web Mercator 座標系 (EPSG:3857) に変換しておきます。

let points = [[139.75, 35.68,], [135.52, 34.68]];
  
//WGS84 緯度経度 (EPSG:4326) から Web Mercator (EPSG:3857) に変換
for (var i = 0; i < points.length; i++) {
    points[i] = ol.proj.transform(points[i], 'EPSG:4326', 'EPSG:3857');
}

const lineFeature = new ol.Feature({
    geometry: new ol.geom.LineString(points)
});

 次に、ラインの見た目を管理する ol.style.Style を定義します。

const lineStyle = new ol.style.Style({
    stroke: new ol.style.Stroke({ color: '#000000', width: 2 })
})

 これらをレイヤーに追加します。ここで、 ol.layer.Vector は Feature 一覧をまとめて管理するオブジェクトになっています。

const lineLayer = new ol.layer.Vector({
    source: new ol.source.Vector({
        features: [lineFeature]
    }),
    style: lineStyle
})

 最後に addLayer() でマップにレイヤーを追加すれば完成です。

map.addLayer(lineLayer);

 全体のソースコードと実装例は以下の通りです。

<!DOCTYPE html>
<html>
<head>
<title>htmlMap</title>
<meta http-equiv='content-type' charset='utf-8'>
<meta name='viewport' content='width=device-width'>
</head>
<body>
<!-- 埋め込みマップのdivタグ。マップサイズはwidth(幅)とheight(高さ)で決まる -->
<div id='mapcontainer' style='width:100%; height:300px; z-index:0;'></div>
<!-- 以下OpenLayersのJavaScriptとCSS -->
<script src="https://cdn.jsdelivr.net/npm/ol@v10.4.0/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.4.0/ol.css">

<script>
function init_map() {
    const map = new ol.Map({
        target: 'mapcontainer',  
        layers: [
           new ol.layer.Tile({
                source: new ol.source.OSM() 
            })
        ],
        view: new ol.View({ 
            center: ol.proj.fromLonLat([137.76, 35.12]),  
            zoom: 6,
            minZoom: 0,
            maxZoom: 18
        })
    });
    
    let points = [[139.75, 35.68,], [135.52, 34.68]];
  
    //WGS84 緯度経度 (EPSG:4326) から Web Mercator (EPSG:3857) に変換
    for (var i = 0; i < points.length; i++) {
        points[i] = ol.proj.transform(points[i], 'EPSG:4326', 'EPSG:3857');
    }

    const lineFeature = new ol.Feature({
        geometry: new ol.geom.LineString(points)
    });

    const lineStyle = new ol.style.Style({
        stroke: new ol.style.Stroke({ color: '#000000', width: 2 })
    })

    const lineLayer = new ol.layer.Vector({
        source: new ol.source.Vector({
            features: [lineFeature]
        }),
        style: lineStyle
    })

    map.addLayer(lineLayer);
}

//ダウンロード時に初期化する
window.addEventListener('DOMContentLoaded', init_map());

</script>
</body>
</html>

実装例

 

関連記事

 Leaflet についてはこちら。

 MapLibre についてはこちら。

 

ちょっと宣伝

 当サイトは Web 地図を積極的に用いた海外旅ブログまとめサイトとなっています。トップページに地図がありますが、地名を押すと画像が開き、画像を押すと関連記事一覧(クリック数順)が開きます。記事数が多い国ほど赤く、地名もその国で記事が多い都市の文字が大きくなるようにしています。ぜひ覗いてみてください。
 当サイトで海外旅ブログを執筆することも可能です(もちろん無料です)! また既にブログをお持ちの方も、当サイトからリンクを貼ることができるようになっています。パントレ開発部までお気軽にお問い合わせください。


 このページが皆様のプログラミングの一助となりますことをお祈りいたします

パントレ開発部