概要
Electron で地図を表示するアプリを作ってみます。
ライブラリとして地図ライブラリはleaflet
を、マーカークラスタのためにleaflet.markercluster
を使います。
それぞれのバージョンは以下のとおりです。
|ライブラリ|バージョン|
|---+---|
|electron|1.12.2|
|leaflet|1.6.0|
|leaflet.markercluster|1.4.1|
準備
node と npm
最短の道
ディレクトリを作成
ディレクトリを名前はなんでもいいので作って、そこに以下の内容の package.json をおきます。ディレクトリの名前はとりあえず le にしておきます。
{
"name": "le",
"version": "1.0.0",
"description": "Sample map application.",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"author": ""
}
Electron をインストール
npm i electron --save
アプリの作成
le の下に以下の3ファイルを作成します。
index.html
<!DOCTYPE html>
<html lang=zxx>
<link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
>
<script
src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
></script>
<style>
html, body, #mapid { height: 100% }
body { margin: 0 }
</style>
<title>Electron-Leaflet</title>
<div id="mapid"></div>
main.js
const { app, BrowserWindow } = require('electron')
const
createWindow = () => {
const mainWindow = new BrowserWindow(
{ width : 1000
, height : 1000
, webPreferences : {
preload : __dirname + '/preload.js'
}
}
)
mainWindow.loadFile( 'index.html' )
}
app.whenReady().then(
() => {
createWindow()
app.on(
'activate'
, () => !BrowserWindow.getAllWindows().length && createWindow()
)
}
)
app.on(
'window-all-closed'
, () => process.platform !== 'darwin' && app.quit()
)
preload.js
window.onload = () => {
const
map = L.map( 'mapid' ).setView( [ 35.6825, 139.752778 ], 15 )
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
).addTo( map )
}
デバッグ
npm run start
勘所
html, body, #mapid { height: 100% }
で地図を囲む全ての要素の height を 100% にしないと地図が表示されません。
body { margin: 0 }
がないと、地図の左上にちょっと余白ができて、右下が切れてしまいます。
L.map( 'mapid' ).setView( [ 35.6825, 139.752778 ], 15 )
で id が mapid の div に地図をつけています。
center と zoom の両方を指定しないと、地図が表示されません。
発展
デフォルトのマーカー
デフォルトのマーカーを皇居に置いてみます。
- preload.js の onload の中に以下の内容を加えます。
L.marker( [ 35.6825, 139.752778 ] ).addTo( map ).bindPopup( 'Imperial Palace.' ).openPopup()
divIcon を使ったマーカー
divIcon を使うと、マーカーのアイコンとして div を使えます。div なんでやりたい放題できます。とりあえず赤いぽっちにしてみます。
- index.html の
<style>
に以下の内容を加えます。
.marker {
text-align : center
; color : white
; font-size : 16
; border-radius : 8px
; box-shadow : 8px 8px 8px rgba( 0, 0, 0, 0.4 )
}
.red {
background : red
}
- preload.js の onload の中に以下の内容を加えます。
const redMarker = { icon: L.divIcon( { className: 'red marker', iconSize: [ 16, 16 ] } ) }
L.marker( [ 35.6825, 139.752778 ], redMarker ).addTo( map ).bindPopup( 'Imperial Palace.' ).openPopup()
マーカークラスターグループ
leaflet.markercluster をインストールすると、地図にたくさんマーカーを置くとき、近接するマーカーをまとめて表示するような機能を実現できます。
とりあえず5個のマーカーのクラスターグループを北の丸公園においてみます。
- index.html に以下の内容を加えます。
<link
rel="stylesheet"
href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.css"
>
<link
rel="stylesheet"
href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.Default.css"
>
<script
src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"
></script>
- preload.js の unload の中に以下の内容を加えます。
map.addLayer(
L.markerClusterGroup().addLayer(
L.marker( [ 35.691, 139.752 ], redMarker )
).addLayer(
L.marker( [ 35.692, 139.752 ], redMarker )
).addLayer(
L.marker( [ 35.690, 139.752 ], redMarker )
).addLayer(
L.marker( [ 35.691, 139.753 ], redMarker )
).addLayer(
L.marker( [ 35.691, 139.751 ], redMarker )
)
)
5個まとめて表示されています。
5 と書いてあるクラスターにズームしてみます。
余談
z-index について
この記事では地図の上に他の HTML エレメントがのっていませんが、たとえばメニューみたいなものを上にのせたいというような場合が考えられます。この時 #mapid の z-index を 0 にするか、上にのせたいものの z-index を 400 以上にする必要があります。
#mapid {
z-index : 0
}
警告について
View メニューから Toggle Developer Tools を選ぶと、HTML のデバッガが出てきて、console をみると以下のような警告が表示されています。
security-warnings.ts:179 Electron Security Warning (Insecure Content-Security-Policy) This renderer process has either no Content Security
Policy set or a policy with "unsafe-eval" enabled. This exposes users of
this app to unnecessary security risks.
For more information and help, consult
https://electronjs.org/docs/tutorial/security.
This warning will not show up
once the app is packaged.
これが気になる方は preload.js の頭で
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = '1'
としてください。
もう一つの方法としてスタンドアローンアプリであれば、index.html に以下のように書けばいいのですが、Leaflet を使う場合はこれを書くと地図データをダウンロードできなくなります。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
Leaflet 1.6.0
前回の記事(Vue で地図を表示する無料で最短の道)を書いた時に比べ Leaflet は少し書きやすくなりました。
また前回は npm でインストールしたのですが、いずれにしろネットワークが必ず必要なので今回は CDN にしてみました。
最後に
leaflet は機能豊富なライブラリなので、いくらでもネタはあるんですが、キリがないのでこのへんにしておきます。最後までおつきあいいただいてありがとうございました。