Google Maps APIで利用して設置できるマーカーは
精々画像が使えるくらいで融通が利かないなと常々思っていた。
画像が使えるのだからPhotoShopなんかで自由にお絵かきすればいいんだけど、
個人的にはDOMをCSSでデザインするほうが楽だし、
クリックなんかのイベントでマーカーの色を変えたりしたい。
#Custom Overlays
結構苦労して探したらどうやらCustom OverlaysなるものでDOMは配置できるらしい。
サンプルなんかも拾えた。
http://www.mwsoft.jp/programming/googlemap/google_map_v3_custom_overlay.html
リファレンスでもサンプルでもprototypeの新しいインスタンスに追加って書いてある。
CustomMarker.prototype = new google.maps.OverlayView();
でもどうせならES6でやりたい。
できもしないのに変に拘る。ハマる元。
#血眼で探したらようやくあったサンプル
https://codepen.io/mock/pen/rWzPeR
これを参考に
/**
* class CustomMarker
*/
export default class CustomMarker extends google.maps.OverlayView{
/**
* constructor
* @param object map
* @param float lat
* @param float lng
* @param boolean isDisplay
* @param boolean isSelected
*/
constructor(map,lat,lng,isDisplay = true,isSelected = false){
super();
this.position = {
lat:lat,
lng:lng
};
this.isDisplay = isDisplay;
this.isSelected = isSelected;
this.setMap(map);
this.el = null;
}
/**
* onAdd
*/
onAdd(){
this.el = document.createElement('div');
const className = 'custom-marker' + ((this.isSelected) ? '--selected': '');
this.el.classList.add(className);
if(!this.isDisplay){
this.el.style.display = 'none';
}
const panes = this.getPanes();
panes.overlayLayer.appendChild(this.el);
// click event
panes.overlayMouseTarget.appendChild(this.el);
google.maps.event.addDomListener(this.el, 'click', () => {
google.maps.event.trigger(this, 'click');
this.setSelected(true);
});
}
/**
* draw
*/
draw(){
if(!this.el) return;
const point = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(this.position.lat, this.position.lng));
this.el.style.position = 'absolute';
this.el.style.left = point.x + 'px';
this.el.style.top = point.y + 'px';
}
/**
* onRemove
*/
onRemove(){
if(!this.el) return;
this.el.parentNode.removeChild(this.el);
this.el = null;
}
/**
* 選択状態のset
*/
setSelected(boolean){
if(boolean === this.isSelected) return;
this.isSelected = boolean;
this.switchClass();
}
/**
* 表示フラグのset
*/
setDisplay(boolean){
if(boolean === this.isDisplay) return;
this.isDisplay = boolean;
this.applyStlyes();
}
/**
* switch class list
*/
switchClass(){
if(!this.el) return;
const className = 'custom-marker' + ((this.isSelected) ? '--selected': '');
this.el.classList.replace(this.el.classList.item(0),className);
}
/**
* apply styles
*/
applyStlyes(){
if(!this.el) return;
this.el.style.display = (!this.isDisplay) ? 'none' : '';
}
}
リファレンスを読む限りではonAdd()
、draw()
、onRemove()
のメソッドを実装しなければいけないらしい、
-
onAdd()
でDOMの用意とイベントの追加 -
draw()
で描画 -
onRemove()
は削除
って認識で合っているのかな?
ついでに選択や表示のフラグを追加して、class名を変えたりstyleを変えたり。
あとは↑のオブジェクトをimportしてGoogle Mapを初期化した後に呼び出す。
import CustomMarker from './CustomMarker';
document.addEventListener('DOMContentLoaded', () => {
initMap();
});
function initMap(){
const lat = 36.0652196;
const lng = 136.219452;
const options = {
gestureHandling: 'greedy',
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: new google.maps.LatLng(lat,lng),
zoom: 14,
clickableIcons: false
};
const map = new google.maps.Map(document.getElementById('map'), options);
const marker = new CustomMarker(map,lat,lng);
document.getElementById('deselected').addEventListener('click',() => {
marker.setSelected(false);
});
document.getElementById('switch-display').addEventListener('click',() => {
marker.setDisplay(!marker.isDisplay);
});
}
CSSで装飾
.custom-marker{
background:#00FF00;
width:10px;
height:10px;
border-radius:50%;
cursor:pointer;
}
.custom-marker--selected{
background:#FF0000;
width:10px;
height:10px;
border-radius:50%;
cursor:pointer;
}
自由にデザインしたいとか言っておいてこのセンス・・・。
とりあえずできたからよし。
あとは用途に合わせてカスタマイズすればいい。
実務ではVueなんかと組み合わせて使ってたりしている。
#リポジトリ
https://github.com/torabe/custom-marker
#感想
結構重宝すると思うんだけど情報少なすぎない?