Leaflet 拡張基礎編 #6 ズームコントロールのカスタマイズ
L.Control.Zoom
L.Control.Zoom は 地図描画時にデフォルトで表示されるズームコントロールです。L.Control のサブクラスとしてあらかじめ提供されています。
今回はこのズームコントロールの見た目や挙動のカスタマイズをしてみます。
デフォルトのズームコントロール
地図コンテナ L.Map はデフォルトのオプションが
zoomControl: true
になっているので、そのままなら上の図のようなズームコントローラが表示されます。
このとき Leaflet はズームコントロール部分の HTML を地図のコントロール領域内に以下のように出力します。
<div id="map" class="leaflet-container ...">
<div class="leaflet-pane leaflet-map-pane"></div>
<div class="leaflet-control-container">
<div class="leaflet-top leaflet-left">
<div class="leaflet-control-zoom leaflet-bar leaflet-control">
<a class="leaflet-control-zoom-in" href="#"
title="Zoom in" role="button" aria-label="Zoom in">+</a>
<a class="leaflet-control-zoom-out" href="#"
title="Zoom out" role="button" aria-label="Zoom out">-</a>
</div>
</div>
<div class="leaflet-top leaflet-right"></div>
<div class="leaflet-bottom leaflet-left"></div>
<div class="leaflet-bottom leaflet-right"></div>
</div>
</div>
5~10行目が L.Control.Zoom の部分です。ズームインとズームアウトのボタンは A タグで、ラベルはテキストになっています。
自分でカスタマイズしたズームコントロールを使いたい場合やそもそもズームコントロールがいらないので出力を抑制したいという場合は、L.Map のインスタンス生成時に
const map = L.map('map', {
// ズームコントローラの生成を抑制
zoomControl: false
});
とし、自前のものを使う場合は改めて定義します。
L.Control.Zoom の簡単なカスタマイズ
オプション指定によるテキストのカスタマイズ
L.Control.Zoom 固有のオプション は4つあって、ボタンのラベルと title 属性の値を任意の文字列にできます。
// デフォルトのズームコントロールは false になっているものとする
L.control.zoom({
// ボタンのラベルを+-から変更
zoomInText: '▲',
zoomOutText: '▼',
// title 属性を日本語化
zoomInTitle: 'ズームイン',
zoomOutTitle: 'ズームアウト'
}).addTo(map);
スタイルのカスタマイズ
ボタンのスタイルを変更したい場合は、先に挙げた HTML 部分を参考に適宜スタイルシートを定義して好みの見た目にします。
.leaflet-bar.leaflet-control-zoom a {
background-color: #445;
color: #fff;
}
L.Control.Zoom の拡張
L.Control.Zoom に設定できるオプションやスタイルシート以外の部分を変えたい場合は、このクラスを独自拡張することになります。
今回はズームコントロールの DOM 要素を一部変更、具体的にはズームコントロールボタンの title 属性を独自定義のツールチップ data-tooltip 属性に置き換えます。
イメージとしては、デフォルトのこんな HTML を
<div class="leaflet-control-zoom leaflet-bar leaflet-control">
<a class="leaflet-control-zoom-in" href="#"
title="Zoom in" role="button" aria-label="Zoom in">+</a>
<a class="leaflet-control-zoom-out" href="#"
title="Zoom out" role="button" aria-label="Zoom out">-</a>
</div>
↓
<div class="leaflet-control-zoom leaflet-bar leaflet-control">
<a class="leaflet-control-zoom-in" href="#"
data-tooltip="Zoom in" role="button" aria-label="Zoom in">+</a>
<a class="leaflet-control-zoom-out" href="#"
data-tooltip="Zoom out" role="button" aria-label="Zoom out">-</a>
</div>
こんなふうに変更して、ツールチップの表示はスタイルシートで管理したいということです。
サブクラスを作成
Leaflet のソースコード leaflet-src.js(現在の最新版は 1.5.1)から L.Control.Zoom が ボタンの DOM 要素を生成している部分を見てみると、
_createButton: function (html, title, className, container, fn) {
var link = create$1('a', className, container);
link.innerHTML = html;
link.href = '#';
link.title = title;
link.setAttribute('role', 'button');
link.setAttribute('aria-label', title);
disableClickPropagation(link);
on(link, 'click', stop);
on(link, 'click', fn, this);
on(link, 'click', this._refocusOnMap, this);
return link;
},
このメソッドを書き換えて title 属性の定義を無くして data-tooltip 属性に内容を書き換えたものを作り、このメソッドを新しいサブクラスのものとして置き換えます。このソースコードはクラスの階層やメソッドの名前などがパッケージ化されたものと所々違っているので、そのあたりはソースコードをよく読んで辻褄を合わせるようにしまして、
L.Control.Zoom.BtoW = L.Control.Zoom.extend({
_createButton: function(html, title, className, container, fn) {
const link = L.DomUtil.create('a', className, container);
link.innerHTML = html;
link.href = '#';
link.setAttribute('role', 'button');
link.setAttribute('aria-label', title);
link.setAttribute('data-tooltip', title);
L.DomEvent.disableClickPropagation(link);
L.DomEvent.on(link, 'click', L.DomEvent.stop);
L.DomEvent.on(link, 'click', fn, this);
L.DomEvent.on(link, 'click', this._refocusOnMap, this);
return link;
}
});
L.control.zoom.botw = function(opts) {
return new L.Control.Zoom.BotW(opts);
};
こんな感じに。元の5行目を削って、新しい方に8行目を追加しただけです。これで L.Control.Zoom を部分的にマイメソッドに書き換えたサブクラスができました。
ではこれを毎度ながら OpenStreetMap のサンプルに読み込んで、新たに追加した data-tooltip 属性をスタイルシートで表示させるようにしてみます。
Leaflet Demo – L.Control.Zoom.BotW
ゲーム地図の方にも追加、前回作った全画面表示コントロールとボタンやツールチップなどの UI のスタイルシートの定義を統一しました(今のところスタイルシートは結構あやしい)。
地図にとりあえずつけたかったベーシックな機能はだいたいこんなところです。
Leaflet の拡張もだいたいやってみたというところで、ここまでを Leaflet 拡張基礎編として、次回からは実世界でいうところの地物となるマーカーのアイコン作成などに入ります。