下記2パターンの店舗検索を実装した際の備忘録
- シンプルな店舗検索
- マーカー クラスタを使用した店舗検索
シンプルな店舗検索
マップに複数マーカーを立てるシンプルな店舗検索。
マーカーが密集すると重なって操作性が悪いため、
店舗数が多く全国展開しているようなサービスには向かない。
公式チュートリアル
実装の流れ
- 地図の作成
- マーカーのデータ(GeoJSON)を読み込んでマーカーを立てる
- マーカーのクリック時の処理を追加する
地図の作成
チュートリアルにある下記のコードが、マップ作成のために必要な最小限のコード。
関数initMap
をAPIのJS読み込みタグにパラメータcallback
に渡すことで、
マーカーのない必要最低限のマップが作成される。
要件に合わせて関数initMap
に処理を追加していく
<!-- The div to hold the map -->
<div id="map"></div>
<script src="app.js"></script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap&solution_channel=GMP_codelabs_simplestorelocator_v1_a"></script>
function initMap() {
// Create the map.
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: { lat: 52.632469, lng: -1.689423 },
});
}
店舗のデータを読み込んでマーカーを立てる
チュートリアルを参考に作成したGeoJSONを、関数initMap
内でmap.data
に渡すことでマップにマーカーが立つ。
function initMap() {
// Create the map.
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: {lat: 52.632469, lng: -1.689423},
});
// Load the stores GeoJSON onto the map.
map.data.loadGeoJson('stores.json', {idPropertyName: 'storeid'});
}
GeoJSONをファイルパスではなく変数で読み込む場合、addGeoJson
を使用する。
const stores =
{
"type": "FeatureCollection",
"features": [{
"geometry": {
"type": "Point",
"coordinates": [-0.1428115,
51.5125168
]
},
"type": "Feature",
"properties": {
"category": "patisserie",
"hours": "10am - 6pm",
"description": "Modern twists on classic pastries. We're part of a larger chain of patisseries and cafes.",
"name": "Josie's Patisserie Mayfair",
"phone": "+44 20 1234 5678",
"storeid": "01"
}
},
};
function initMap() {
// Create the map.
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: {lat: 52.632469, lng: -1.689423},
});
// GeoJSONを変数で渡す場合
map.data.addGeoJson(stores);
}
マーカーのクリック時の処理を追加する
map.data.addListener
にクリックイベントを追加する。
infoWindow
はマーカーの周りに表示されるポップアップで、ソースコードや表示位置などを設定できる。
function initMap() {
// Create the map.
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: {lat: 52.632469, lng: -1.689423},
});
// Load the stores GeoJSON onto the map.
map.data.loadGeoJson('stores.json', {idPropertyName: 'storeid'});
const infoWindow = new google.maps.InfoWindow();
// Show the information for a store when its marker is clicked.
map.data.addListener('click', (event) => {
const category = event.feature.getProperty('category');
const name = event.feature.getProperty('name');
const description = event.feature.getProperty('description');
const hours = event.feature.getProperty('hours');
const phone = event.feature.getProperty('phone');
const position = event.feature.getGeometry().get();
const content = `
<h2>${name}</h2><p>${description}</p>
<p><b>Open:</b> ${hours}<br/><b>Phone:</b> ${phone}</p>
`;
infoWindow.setContent(content);
infoWindow.setPosition(position);
infoWindow.setOptions({pixelOffset: new google.maps.Size(0, -30)});
infoWindow.open(map);
});
}
マーカー クラスタを使用した店舗検索
密集したマーカーをクラスタ化した店舗検索。
店舗数が多く全国展開しているサービスでは、
マーカーのクラスタ化が必要になる場合が多い。
公式チュートリアル
チュートリアルが古いマーカーgoogle.maps.Marker
を使用した例のため、
下記を参考に新しいマーカーAdvancedMarker
を使用する。
実装の流れ
- Marker Clustererの読み込み
- 地図の作成
- マーカー配列を読み込んでマーカーを立てる
- マーカーのクリック時の処理を追加する
Marker Clustererの追加
マーカーのクラスタ化するにはmarkerclusterer
というJSを追加で読み込む。
読み込み方法は色々あるが、下記はCDNを使用する例
<!-- The div to hold the map -->
<div id="map"></div>
<script src="https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js"></script>
<script src="app.js"></script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap&solution_channel=GMP_codelabs_simplestorelocator_v1_a"></script>
地図の作成
新しいマーカーAdvancedMarker
を使用する場合、mapId
が必要になるため追加する。
function initMap() {
// Create the map.
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: { lat: 52.632469, lng: -1.689423 },
mapId: 'MAP_ID', // AdvancedMarkerを使用する場合必須
});
}
window.initMap = initMap;
マーカー配列を読み込んでマーカーを立てる
チュートリアルを参考に店舗の座標をまとめた配列locations
を定義し、
locations
をmapしマーカー配列markers
を作成する。
古いマーカーの記述は新しいマーカーAdvancedMarker
のものに書き換える必要があるが、
チュートリアルの記法も一部古いため下記の記事を参考に修正する。
修正箇所は下記クラス名
-
google.maps.marker.AdvancedMarkerView
→google.maps.marker.AdvancedMarkerElement
-
google.maps.marker.PinView
→google.maps.marker.PinElement
function initMap() {
// Create the map.
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: { lat: 52.632469, lng: -1.689423 },
mapId: 'MAP_ID',
});
// Create an array of alphabetical characters used to label the markers.
const labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Add some markers to the map.
const markers = locations.map((position, i) => {
const label = labels[i % labels.length];
// 古いマーカー
//const marker = new google.maps.Marker({
// position,
// label,
//});
// 新しいマーカー
const pin = new google.maps.marker.PinElement({
scale: 1.5, // マーカーの大きさ( 等倍: 1)
background: '#e44631', // マーカーの色
borderColor: '#b01500', // マーカーの輪郭の色
glyphColor: '#b01500', // グリフの色
// glyph: '', // グリフを非表示にする場合
});
const marker = new google.maps.marker.AdvancedMarkerElement({
map,
position: position,
content: pin.element
});
return marker;
});
// Add a marker clusterer to manage the markers.
// CDN用の記述に修正
const markerCluster = new markerClusterer.MarkerClusterer({ map, markers });
}
const locations = [
{ lat: -31.56391, lng: 147.154312 },
{ lat: -33.718234, lng: 150.363181 },
{ lat: -33.727111, lng: 150.371124 },
{ lat: -33.848588, lng: 151.209834 },
{ lat: -33.851702, lng: 151.216968 },
{ lat: -34.671264, lng: 150.863657 },
{ lat: -35.304724, lng: 148.662905 },
{ lat: -36.817685, lng: 175.699196 },
{ lat: -36.828611, lng: 175.790222 },
{ lat: -37.75, lng: 145.116667 },
{ lat: -37.759859, lng: 145.128708 },
{ lat: -37.765015, lng: 145.133858 },
{ lat: -37.770104, lng: 145.143299 },
{ lat: -37.7737, lng: 145.145187 },
{ lat: -37.774785, lng: 145.137978 },
{ lat: -37.819616, lng: 144.968119 },
{ lat: -38.330766, lng: 144.695692 },
{ lat: -39.927193, lng: 175.053218 },
{ lat: -41.330162, lng: 174.865694 },
{ lat: -42.734358, lng: 147.439506 },
{ lat: -42.734358, lng: 147.501315 },
{ lat: -42.735258, lng: 147.438 },
{ lat: -43.999792, lng: 170.463352 },
];
window.initMap = initMap;
マーカーのクリック時の処理を追加する
infoWindow
を定義してmaker
にaddListener
でイベントを追加する。
function initMap() {
// Create the map.
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: { lat: 52.632469, lng: -1.689423 },
mapId: 'MAP_ID',
});
const infoWindow = new google.maps.InfoWindow({
content: "",
disableAutoPan: true,
});
// Create an array of alphabetical characters used to label the markers.
const labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Add some markers to the map.
const markers = locations.map((position, i) => {
const label = labels[i % labels.length];
// 古いマーカー
//const marker = new google.maps.Marker({
// position,
// label,
//});
// 新しいマーカー
const pin = new google.maps.marker.PinElement({
scale: 1.5, // マーカーの大きさ( 等倍: 1)
background: '#e44631', // マーカーの色
borderColor: '#b01500', // マーカーの輪郭の色
glyphColor: '#b01500', // グリフの色
// glyph: '', // グリフを非表示にする場合
});
const marker = new google.maps.marker.AdvancedMarkerElement({
map,
position: position,
content: pin.element
});
// markers can only be keyboard focusable when they have click listeners
// open info window when marker is clicked
marker.addListener("click", () => {
infoWindow.setContent(label);
infoWindow.open(map, marker);
});
return marker;
});
// Add a marker clusterer to manage the markers.
// CDN用の記述に修正
const markerCluster = new markerClusterer.MarkerClusterer({ map, markers });
}
const locations = [
{ lat: -31.56391, lng: 147.154312 },
{ lat: -33.718234, lng: 150.363181 },
{ lat: -33.727111, lng: 150.371124 },
{ lat: -33.848588, lng: 151.209834 },
{ lat: -33.851702, lng: 151.216968 },
{ lat: -34.671264, lng: 150.863657 },
{ lat: -35.304724, lng: 148.662905 },
{ lat: -36.817685, lng: 175.699196 },
{ lat: -36.828611, lng: 175.790222 },
{ lat: -37.75, lng: 145.116667 },
{ lat: -37.759859, lng: 145.128708 },
{ lat: -37.765015, lng: 145.133858 },
{ lat: -37.770104, lng: 145.143299 },
{ lat: -37.7737, lng: 145.145187 },
{ lat: -37.774785, lng: 145.137978 },
{ lat: -37.819616, lng: 144.968119 },
{ lat: -38.330766, lng: 144.695692 },
{ lat: -39.927193, lng: 175.053218 },
{ lat: -41.330162, lng: 174.865694 },
{ lat: -42.734358, lng: 147.439506 },
{ lat: -42.734358, lng: 147.501315 },
{ lat: -42.735258, lng: 147.438 },
{ lat: -43.999792, lng: 170.463352 },
];
window.initMap = initMap;
参考