logo-sm

お問い合わせは Webフォームから

ブログ

OpenLayersのWebGLPointsLayerを使ってみる

2021.04.23

■ はじめに

OpenLayers6でWebGL関連の機能の変更がありました。追加された機能の一つに、WebGLPointsレイヤーがあります。地図上に大量のポイントを描画することができる機能で、OpenLayersのサンプルでは、8万ものアイコンが描画されています。ポイントの表示に全振りした面白い機能なので、使い方を紹介したいと思います。

 

■ OpenLayersとは

地図アプリケーションの製造に特化したオープンソースのJavaScriptライブラリです。

・Webページ上に地図を表示する。

・地図上でスクロールやズームの操作を行えるようにする。

・地図上に図形や画像を表示する。

これらの機能を簡単に実装することができます。

 

■ WebGLとは

ブラウザ上で、3Dの描画を行う機能です。

GPUを利用することで、Webブラウザ上では負荷のかかる3Dの描画処理を高速で行うことができます。

HTML5の標準仕様として利用でき、Canvas上で描画を行うことが出来るため、プラグインの実装などが不要です。

2Dの描画でも利用でき、OpenLayersでは、大量のポイントの描画や、アニメーションの表示に利用しています。

 

■ OpenLayers導入

OpenLayersは下記サイトから取得することができます。

https://openlayers.org/

CDNも用意されている為、今回はこちらを利用してサンプルを作成したいと思います。

まずは、ブラウザ上に地図を表示してみます。

 

■ サンプル

●index.html

<!doctype html>
<html lang="ja">
  <head>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css" type="text/css">
    <style>
      .map {
        height: 500px;
        width: 100%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
    <title>WebGLTest</title>
  </head>
  <body>
    <h2>WebGLサンプル</h2>
    <div id="map" class="map"></div>
    <script type="text/javascript" th:src="@{/index.js}"></script>
  </body>
</html>

●index.js

var map = new ol.Map({
	target: 'map',
	layers: [
		new ol.layer.Tile({
			source: new ol.source.OSM()
		}),
	view: new ol.View({
		center: ol.proj.fromLonLat([140.00, 36.00]),
		zoom: 8 
	}) 
});

上記ソースをブラウザで表示すると以下のように表示されます。

この状態で既に、地図上でのスクロール・ズームの操作が実装されています。
動作も軽くて、操作していて気持ちが良いです。

地理データは、「OpenStreetMap」を利用しています。

「OpenStreetMap」はOpenStreetMap Foundationのオープンソースの地図を作成するプロジェクトによって作成された地図データです。

ライセンスの詳細は以下サイトにあります。

https://www.openstreetmap.org/copyright

 

■ WebGL機能を使う

ではさっそく、作成した地図に、WebGLPointsLayerを利用した描画をしていきたいと思います。

先ほど作成したindex.jsに下記を追記します。

●index.js

//座標情報作成
var geojsonObject = {
	'type': 'FeatureCollection',
	'crs': {
		'type': 'name',
		'properties': {
			'name': 'EPSG:4326',
		},
	},
	'features': [{
		'type': 'Feature',
		"properties": {
			'colorType':'typeA',
			'shape': 'circle'
		},
		'geometry': {
			'type': 'Point',
			'coordinates': ol.proj.fromLonLat([135.00, 36.00]),
		}
	}, {
		'type': 'Feature',
		"properties": {
			'colorType':'typeB',
			'shape': 'cross'
		},
		'geometry': {
			'type': 'Point',
			'coordinates': ol.proj.fromLonLat([140.00, 36.00]),
		}
	}]
};

var features = new ol.format.GeoJSON().readFeatures(geojsonObject);
var vectorSource = new ol.source.Vector({
	features: features,
});

//スタイルの設定
var colorA = [255, 0, 0];
var colorB = [0, 255, 0];
var colorC = [0, 0, 255];

var size = 16;

var style = {

	symbol: {
		symbolType: 'image',
		src: 'basepct.PNG',
		size: size,
		color: [
		'match',
		['get','colorType'],
		'typeA',colorA,
		'typeB',colorB,
		colorC
		],
		rotateWithView: false,
		offset: [0, 0],
		textureCoord: [
			'match',
			['get', 'shape'],
			'circle',[0, 0, 0.5, 0.5],
			'cross',[0.5, 0, 1, 0.5],
			'square',[0, 0.5, 0.5, 1],
			'triangle',[0.5, 0.5, 1, 1],
			[0, 0, 0.5, 0.5],
		]
	},
};

//レイヤーを作成し、マップに追加
//ol/layer/WebGLPoints
map.addLayer(
	new ol.layer.WebGLPoints({
		source: vectorSource,
		style: style,
	})
);

basepct.PNG
実行時の表示は以下。
ソースは上から
・座標情報作成
・スタイルの設定
・レイヤーを作成し、マップに追加

といった処理を行っています。


●座標情報作成

OpenLayersで地図上に画像や図形を表示するには、

  1. 1.featureの作成
  2. 2.sourceの作成
  3. 3.sourceにfeatureを追加
  4. 4.styleの作成
  5. 5.レイヤーの作成
  6. 6.レイヤーにsourceとstyleを追加
  7. 7.マップにレイヤーを追加

といった工程が必要になります。

featureは、座標情報や、点やライン、ポリゴンなどの形状情報、画像の設定などを持ちます。

今回は、geojson形式で地理情報を作成し、featureを作成しています。

geojsonのフォーマットに関しては、以下サイトを確認して下さい。

参考:https://ja.wikipedia.org/wiki/GeoJSON

 

features配下のpropertiesには、自由に項目を追加できます。「colorType」と、「shape」は私が追加した項目です。

WebGLPointsレイヤーでは、このpropertiesの項目を参照して、条件を設定し、形状や色の変更を行えます。

propertiesは、feature作成後、setPropertiesメソッドで追加することもできます。

 

●スタイル作成

ここでは、レイヤーがfeatureをどのように表示するかを設定しています。

Layerレイヤーでは、featureごとにスタイルの設定ができますが、WebGLPointsLayerでは、featureごとの設定はできず、レイヤーのスタイル設定をすべてのfeatureに反映します。各項目について紹介します。

 

・symbolType

featureを表示する方法を設定します。imageなら画像、circleなら円を表示します。

・src

画像のurlを設定します。

通常Vectorレイヤーでアイコンを表示する場合、featureごとにsrcを設定しますが、PointsLayerではstyleで設定します。

また、画像はレイヤーに対して一枚しか設定できません。複数のアイコンを表示したい場合は、basepct.PNGのように、表示する画像を結合した画像を用意する必要があります。

・size

表示する図形・画像の大きさを設定します。

・color

featureの色を設定します。basepct.PNGのように、白地の画像であれば、設定した色がそのまま表示されますが、元々色のある画像の場合、設定した色が画像に足されたような表示になります。

・rotateWithView

図形を回転させたときに、featureも回転させるかを設定します。今回のソースでは、マップは回転しません。

・offset

featureに設定した座標から、offsetで設定した値だけずらして表示します。

・textureCoord

srcで設定した画像の表示範囲をを設定します。

画像の左上を(0,0)右下を(1,1)とし、表示範囲を[左上横,左上縦,右下横,右下縦]のように設定します。

画像の左半分を表示したい場合は、

[0, 0, 0.5, 1]

のように設定します。

 

いくつか項目を紹介しましたが、項目に対して、一つの設定のみだと。地図上に表示する画像・色・大きさは全て同じになってしまいます。

featureの設定に応じて、表示の内容を変えて変えたい場合は、サンプルの「color」・「textureCood」で行っているような記載が必要です。

<textureCoodの例>

・’match’, 

条件と一致した値を返します。

・[‘get’, ‘項目名’], 

featureのpropertiesから指定した項目の値を取得します。

・’circle’, [0, 0, 0.5, 0.5],

shapeの値がcircleであれば、textureCoordを[0, 0, 0.5, 0.5]に設定します。

・…[0, 0, 0.5, 0.5]

最後に一致するものがなかった場合のデフォルト値を設定しています。

matchを利用する場合は必ず設定が必要です。

 

また一致した場合のみ変化させるのではなく、中間の値を補完しながら、徐々に変化させることもできます。

colorの設定を以下に置き換えると、ズームするごとに、色が変わるスタイルになります。

color: [
	‘interpolate’,
	[‘linear’],
	[‘zoom’],
	5,colorA,
	10,colorB
],

・’interpolate’ 

設定された値を徐々に変化させます。

・[‘linear’]

変化が均等に行われる設定です。

・[‘zoom’] 

現在のズームレベルを取得します。

 

このようにstyleに条件を加えていくことで、WeebGLPointsレイヤーで変化のある表示を行うことができます。

より詳細な設定に関しては、以下を参考にして下さい。

https://openlayers.org/en/latest/examples/webgl-points-layer.html

 

●レイヤーの作成とマップ

最後に、WebGLPointsレイヤーの作成を行います。Vectorレイヤーの作成と同様に、

sourceとstyleを設定し、マップに追加することで表示することができます。

 

■ 大量の表示を行う

これまでの工程で、WebGLでの描画は成功しました。

しかし、WebGLPontsLayerは、大量の点の描画に特化したレイヤーです。

なので、地理情報を増やし、大量の表示を試してみたいと思います。

 

geojson作成部の下に以下のソースを追加します。

●index.js

//geojsonObject量産
//座標の範囲
//軽度 125~150 緯度 30~40
var createGeojson = function(){
	for(let i = 0 ; i < 100000 ; i++){

		var type = "typeA";
		var shape = "circle";

		var randomA = Math.random();
		var randomIntA = Math.floor(randomA * 1000) % 25;
		var randomB = Math.random();
		var randomIntB = Math.floor(randomB * 1000) % 20;

		var typeNo = Math.floor(Math.random() * 1000) % 4;
		var shapeNo = Math.floor(Math.random() * 1000) % 4;

		if(typeNo==0){
			type = "typeA"
		}else if(typeNo==1){
			type = "typeB"
		}else if(typeNo==2){
			type = "typeC"
		}else if(typeNo==3){
			type = "typeD"
		}
		if(shapeNo==0){
			shape = "circle"
		}else if(shapeNo==1){
			shape = "cross"
		}else if(shapeNo==2){
			shape = "square"
		}else if(shapeNo==3){
			shape = "triangle"
		}

		var tmpObj={
			type:'Feature'
		};

		tmpObj.properties ={
			colorType: type,
			shape: shape
		}

		tmpObj.geometry={
			'type': 'Point',
			'coordinates': ol.proj.fromLonLat([125.00+randomIntA+randomA, 30.00+randomIntB+randomB])
		}

		geojsonObject.features.push(tmpObj);
	}
}
createGeojson();

合わせて、アイコンの表示を大きめにしているので、styleのアイコンのサイズも16から8に変更し、見やすくします。

 

●表示

ズームを引くと以下のようになります。

10万ポイントを表示しましたが、表示も重くなく、ズームや移動の操作も快適に行えるます。

ランダムなので、地点・図形に特に意味はないですが、それでもこう大量に表示できると、それだけで面白いです。


■ 終わりに

WebGLPointsLayerは、ポイントしか表示できないことや、style、画像を専用に用意しないといけない為、使いやすい機能ではないですが、

大量に同じパターンの図形を表示するという条件に合えば、高速な表示が可能であり、アニメーションなどを加えれれば、これまでにできなかった表現が可能になります。

魅力的で、面白い機能なので是非試して頂きたいと思います。

 

■参考

OpenLayresのサイトは、ドキュメントもわかりやすく、作成例も充実しています。いつも助けられています。

OpenLayersHP: https://openlayers.org/OpenlLayersWorkshop

Workshop:https://openlayers.org/workshop/en/webgl/OpenlLayers

WebGLPointsLayerサンプル:https://openlayers.org/en/latest/examples/icon-sprite-webgl.html

関連記事

  • WindowsのWSL2上のDockerでup時に’ContainerConfig’のエラーが出た。
    当社の開発環境はMacとWindowsが混在したDocker上での開発を行っています。なのでMacでOKだけど […]

    2024.04.08

  • VSCode (内のPowerShell)でアドレス設定を切り替え!
    【経緯】 最近携わった案件で大量のNW機器のキッティングをした際、それぞれにSSHでの接続性などを確認するテス […]

    2023.10.13

  • PaloaltoでWindows NTPサーバに同期
    【事象と対処法】 オフライン環境のPaloaltoでNTPの機能確認をする必要があり、Windows標準のNT […]

    2023.10.13

  • パートナー

  • 人材育成・採用情報