オープンな地図データである OSM(OpenStreetMap) と、オープンな地図操作 JavaScript ライブラリである Leaflet.js を使うことで、ライセンスフリーな地図アプリを作ることができます。このブログでも過去に何度か扱ったことがあります:
http://dotnsf.blog.jp/tag/leaflet
例えば、単に地図を全画面表示するのであればこんな感じのコードを書くと実現できちゃいます:
(東京あたりを中心に、ズームレベル9で地図を表示)
さて、上図の左上にズームコントロールがあります(上記コードでは特に指定していませんが、明示的に非表示にしない限り、デフォルトでズームコントロールが表示されます)。スマホであればピンチイン・アウトの操作でズームイン・アウトができるのですが、タッチスクリーンに対応していない PC のブラウザで地図を見ている場合は、このコントールを使ってズームイン・アウトを行うことになります。
ただ例えば画面上部に常に表示されるメッセージがある場合など、メッセージとズームコントロールが重なってしまい、操作しにくくなってしまうことがあります:
(画面上のメッセージとズームコントロールが重なってしまう例)
この状態をなんとか回避できないか、というのが今回のブログエントリのテーマです。メッセージ側の位置を変えるのは簡単ですが、当然意図があって画面上部にメッセージを表示しているわけですから、できればズームコントロールの位置を変えたい。一方、なまじデフォルトで表示されてしまっているズームコントロールだけにどうすると位置を変更できるのか、がわかりにくいのでした。
正解の一例を先にお見せすると、こんな感じになります:
青字部分が肝になります。初期化時(L.map() 実行時)のオプションで zoomControl: false をつけることでズームコントロールを(一旦)非表示にします。なおもう一つ指定しているオプション dragging: true は地図のスクロール(ドラッグ)ができるようにするオプションで、ここを false にするとスクロールできない地図になります。
このままだとズームコントロールは表示されないのですが、直後の1行でズームコントロールを再び表示しています。そしてこの行では position: 'bottomright' というオプションをつけることで「右下」にズームコントロールを表示させています(デフォルトは 'topleft'):
↑こんな感じになって、メッセージと重ならない位置にズームコントロールを移動できました。
(参考)
https://www.wrld3d.com/wrld.js/latest/docs/leaflet/L.Control.zoom/
http://dotnsf.blog.jp/tag/leaflet
例えば、単に地図を全画面表示するのであればこんな感じのコードを書くと実現できちゃいます:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta charset="utf8"/>
<meta http-equiv="pragma" content="no-cache"/>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.js"></script>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<meta name="apple-mobile-web-app-title" content="OSM Sample"/>
<title>OSM Sample</title>
<script>
</script>
<script>
//. 初期中心位置
var lat = 35.681377778;
var lng = 139.76736389;
//. 初期ズームレベル
var zoomlevel = 9;
var map = null;
$(function(){
//. 初期位置を中心とした地図を OpenStreetMap データで表示
map = L.map('demoMap', {}).setView( [ lat, lng ], zoomlevel );
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © <a href="//openstreetmap.org/">OpenStreetMap</a>',
}
).addTo( map );
});
</script>
<style>
html, body {
width: 100%;
height: 100%;
padding: 0px;
margin: 0px;
}
#demoMap{
position: fixed;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div>
<div id="demoMap"></div>
</div>
</body>
</html>
(東京あたりを中心に、ズームレベル9で地図を表示)
さて、上図の左上にズームコントロールがあります(上記コードでは特に指定していませんが、明示的に非表示にしない限り、デフォルトでズームコントロールが表示されます)。スマホであればピンチイン・アウトの操作でズームイン・アウトができるのですが、タッチスクリーンに対応していない PC のブラウザで地図を見ている場合は、このコントールを使ってズームイン・アウトを行うことになります。
ただ例えば画面上部に常に表示されるメッセージがある場合など、メッセージとズームコントロールが重なってしまい、操作しにくくなってしまうことがあります:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta charset="utf8"/>
<meta http-equiv="pragma" content="no-cache"/>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.js"></script>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<meta name="apple-mobile-web-app-title" content="OSM Sample"/>
<title>OSM Sample</title>
<script>
</script>
<script>
//. 初期中心位置
var lat = 35.681377778;
var lng = 139.76736389;
//. 初期ズームレベル
var zoomlevel = 9;
var map = null;
$(function(){
//. 初期位置を中心とした地図を OpenStreetMap データで表示
map = L.map('demoMap', {}).setView( [ lat, lng ], zoomlevel );
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © <a href="//openstreetmap.org/">OpenStreetMap</a>',
}
).addTo( map );
});
</script>
<style>
html, body {
width: 100%;
height: 100%;
padding: 0px;
margin: 0px;
}
#demoMap{
position: fixed;
width: 100%;
height: 100%;
}
#message{
position: absolute;
top: 10px;
font-size: 20px;
color: red;
font-weight: bold;
}
</style>
</head>
<body>
<div>
<div id="demoMap"></div>
<div id="message">このメッセージが邪魔でズーム制御ができない?</div>
</div>
</body>
</html>
(画面上のメッセージとズームコントロールが重なってしまう例)
この状態をなんとか回避できないか、というのが今回のブログエントリのテーマです。メッセージ側の位置を変えるのは簡単ですが、当然意図があって画面上部にメッセージを表示しているわけですから、できればズームコントロールの位置を変えたい。一方、なまじデフォルトで表示されてしまっているズームコントロールだけにどうすると位置を変更できるのか、がわかりにくいのでした。
正解の一例を先にお見せすると、こんな感じになります:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta charset="utf8"/>
<meta http-equiv="pragma" content="no-cache"/>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.js"></script>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<meta name="apple-mobile-web-app-title" content="OSM Sample"/>
<title>OSM Sample</title>
<script>
</script>
<script>
//. 初期中心位置
var lat = 35.681377778;
var lng = 139.76736389;
//. 初期ズームレベル
var zoomlevel = 9;
var map = null;
$(function(){
//. 初期位置を中心とした地図を OpenStreetMap データで表示
map = L.map('demoMap', { dragging: true, zoomControl: false }).setView( [ lat, lng ], zoomlevel );
L.control.zoom( { position: 'bottomright' } ).addTo( map );
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © <a href="//openstreetmap.org/">OpenStreetMap</a>',
}
).addTo( map );
});
</script>
<style>
html, body {
width: 100%;
height: 100%;
padding: 0px;
margin: 0px;
}
#demoMap{
position: fixed;
width: 100%;
height: 100%;
}
#message{
position: absolute;
top: 10px;
font-size: 20px;
color: red;
font-weight: bold;
}
</style>
</head>
<body>
<div>
<div id="demoMap"></div>
<div id="message">このメッセージがあってもズーム制御できる</div>
</div>
</body>
</html>
青字部分が肝になります。初期化時(L.map() 実行時)のオプションで zoomControl: false をつけることでズームコントロールを(一旦)非表示にします。なおもう一つ指定しているオプション dragging: true は地図のスクロール(ドラッグ)ができるようにするオプションで、ここを false にするとスクロールできない地図になります。
このままだとズームコントロールは表示されないのですが、直後の1行でズームコントロールを再び表示しています。そしてこの行では position: 'bottomright' というオプションをつけることで「右下」にズームコントロールを表示させています(デフォルトは 'topleft'):
↑こんな感じになって、メッセージと重ならない位置にズームコントロールを移動できました。
(参考)
https://www.wrld3d.com/wrld.js/latest/docs/leaflet/L.Control.zoom/