ElectronでOpenLayers3を使ってみる。(その1)
タイトルの通りです。地形データを使ったアプリケーションを作る必要があるのですが、面倒なことはやりたくないので、便利なものは使わせてもらう方向で勉強中です。
なので、以降で掲示したソースも、まだ様々なサンプルの張り合わせです。徐々に自分の書いた箇所が増えていけば良いな。
ソフト等 | バージョン | 備考 |
---|---|---|
Electron | V1.4.4 | Electron公式 |
OpenLayers3 | v3.19.1 | Openlayers3公式 |
国土地理院タイル | 色別標高図 | 地理院タイル一覧 |
準備
Electronの導入は簡単ですし、Qiitaにも情報は多いので割愛します。Nodeからnpmで入れても、公式から、各OS環境用のzipをダウンロードしてきて解凍しても問題ありません。
任意の場所に、アプリケーション用のフォルダを以下のように作ります。
なお、olフォルダの中の、ol.cssとol.jsは、OpenLayers3のものです。公式からダウンロードしてきて解凍後、ここに置きました。
package.json
特に説明する必要もありません。nameとlicenseしか触っていません。
{
"name": "Map Sample (Powerd by Electron & OpenLayers3)",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "MIT"
}
index.js
Electron関連のjs。今後は、アプリケーションメニューなど変更して行きたいので、Electron-APIの勉強が必要かと思っています。
'use strict';
// Electronのモジュール
const electron = require("electron");
// アプリケーションをコントロールするモジュール
const app = electron.app;
// ウィンドウを作成するモジュール
const BrowserWindow = electron.BrowserWindow;
// メインウィンドウはGCされないようにグローバル宣言
let mainWindow;
// 全てのウィンドウが閉じたら終了
app.on('window-all-closed', function() {
if (process.platform != 'darwin') {
app.quit();
}
});
// Electronの初期化完了後に実行
app.on('ready', function() {
// メイン画面の表示。ウィンドウの幅、高さを指定できる
mainWindow = new BrowserWindow({width: 800, height: 600});
mainWindow.loadURL('file://' + __dirname + '/index.html');
// ウィンドウが閉じられたらアプリも終了
mainWindow.on('closed', function() {
mainWindow = null;
});
});
index.html
ほぼOpenLayers3のExamplesから切り貼りしただけ。少しコメントを入れてますが、メモとして書いただけです。地図の下にあるformはメニューに入れたいところ。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="content-script-type" content="text/javascript">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- OpenLayers3 参照 -->
<link rel="stylesheet" href="ext/ol/ol.css" type="text/css">
<script src="ext/ol/ol.js" type="text/javascript"></script>
<!-- 自作外部ファイル 参照 -->
<link rel="stylesheet" href="sample.css" type="text/css">
<script src="sample.js" type="text/javascript"></script>
</head>
<body onload="init_map()">
<div id="screen_top">
<!-- 地図本体 -->
<div id="map"></div>
<!-- 地図下部 -->
<form class="form-inline">
<label>TypeSelect</label>
<select id="type">
<option value="Point">Point</option>
<option value="LineString">LineString</option>
<option value="Polygon">Polygon</option>
</select>
</form>
<!-- コメント -->
<hr>
<pre>
ドラッグ:地図移動。Shift+ALT+ドラッグ:地図回転。Shift+ドラッグ:選択範囲を拡大。Ctrl+ホイール:拡大縮小。
Point:クリックで点を追加。既存の点やラインをドラッグすると移動。Shift+既存の点をクリックで削除。
LineString:クリックで連続線を追加。ダブルクリックで終点を追加。
Polygon:クリックで連続線を追加。始点を選んでクリックするか、ダブルクリックで始点まで閉じる。
</pre>
</div>
</body>
</html>
sample.css
ほぼ、参考にさせていただいたサイトのソースのままです。
div.fill {width: 100%; height: 100%;}
body {width: inherit; height:inherit; padding: 0; margin: 0}
html, body, #map {height: 100%; width: 100%;}
.ol-attribution {
padding: 3px; position: absolute; background-color:#ffffff;
background-color:rgba(230,255,255,0.7);
right: 3px; bottom:5px; font-size:12px;
}
.ol-attribution ul { padding: 0px; line-height: 14px; margin: 0px; }
.ol-attribution li { line-height: inherit; display: inline; list-style: none outside none; }
.ol-zoom .ol-zoom-out { margin-top: 202px; }
.ol-zoomslider { background-color: transparent; top: 2.3em; }
.ol-touch .ol-zoom .ol-zoom-out { margin-top: 212px; }
.ol-touch .ol-zoomslider { top: 2.75em; }
sample.js
参考にさせていただいたサイトのソースに、OpenLayers3のExamplesから切り貼りして、細部を好みで直した程度です。
// ===================================================================
var center_lon = 136.881505; // 中心の経度
var center_lat = 35.171130; // 中心の緯度
var initZoom = 8; // ズームの初期値
var MinZoom = 6; // ズームの最小値(最も広い範囲)
var MaxZoom = 17; // ズームの最大値(最も狭い範囲)
// *******************************************************************
function init_map() {
// 表示用の view 変数の定義。
var view = new ol.View({
projection: "EPSG:3857",
maxZoom: MaxZoom,
minZoom: MinZoom
})
// layer(地理院地図の色別標高図)用の変数
var lay = new ol.layer.Tile({
source: new ol.source.XYZ({
attributions: [ new ol.Attribution({
html: "<a href='http://maps.gsi.go.jp/development/ichiran.html' target='_blank'>国土地理院</a>"
}) ],
url: "http://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png",
projection: "EPSG:3857"
})
})
// 地図変数 (map 変数) の定義。地理院地図を表示するように指定している。
var map = new ol.Map({
target: document.getElementById('map'),
layers: [lay],
view: view,
renderer: ['canvas', 'dom'],
controls: ol.control.defaults().extend([new ol.control.ScaleLine()]),
interactions: ol.interaction.defaults()
});
// zoom slider の追加
map.addControl(new ol.control.ZoomSlider());
// 中心の指定。view に対して指定。transform を忘れないこと。
view.setCenter(ol.proj.transform([center_lon, center_lat], "EPSG:4326", "EPSG:3857"));
// zoom の指定。view に対して指定する。
view.setZoom(initZoom);
// 各ベクター等のスタイル
var features = new ol.Collection();
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector({features: features}),
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: '#ff3333',
width: 3
}),
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: '#ff3333'
})
})
})
});
featureOverlay.setMap(map);
var modify = new ol.interaction.Modify({
features: features,
// the SHIFT key must be pressed to delete vertices, so
// that new vertices can be drawn at the same position
// of existing vertices
deleteCondition: function(event) {
return ol.events.condition.shiftKeyOnly(event) &&
ol.events.condition.singleClick(event);
}
});
map.addInteraction(modify);
var draw; // global so we can remove it later
var typeSelect = document.getElementById('type');
function addInteraction() {
draw = new ol.interaction.Draw({
features: features,
type: /** @type {ol.geom.GeometryType} */ (typeSelect.value)
});
map.addInteraction(draw);
}
/**
* Handle change event.
*/
typeSelect.onchange = function() {
map.removeInteraction(draw);
addInteraction();
};
addInteraction();
}
画面イメージ
現在の画面イメージは次のような感じ。
地図上に点や線がおけるようになりました。
今後は、座標を使って色々な処理ができるようにしていく予定。