LoginSignup
2
2

More than 3 years have passed since last update.

Google Mapsでマーカーラベルを大量に付けると ごちゃごちゃになるのを解決する

Last updated at Posted at 2020-11-11

今日もまた「霊園ガイドサイト開発日記」のスタイルで書いてみます。

今回は前回のGoogle Maps APIの記事のシリーズになります。

霊園ガイドは一目でわかる通り、Google Mapsなどの枯れたマッシュアップを中心に据えています。そんなわけで、Google Maps APIのネタには事欠きません(^^;
霊園ガイドサイト 

さて、今日取り上げるのは「Google Mapsでマーカーラベルを大量に付けると
ごちゃごちゃになる問題」です。

つまりこれですね。下の2枚の画像の左側は、zoomが16の時のものですが、そのズームを12にすると文字がごちゃごちゃになって読めなくなります。

image.png

動作を確認してみる

では実際に目で見て確認してみましょう。
デモページ: https://reien.top/blog/test/gmap/marker/2020-11-12-1.html

デモページにいてみると下の画像のようにズームボタンのついた地図があります。これをクリックしてズーム値を低い値(たとえば12)にすると字が読めなくなるのを確認できます。
image.png

つまり地図を俯瞰するとこうなってしまうわけです。
image.png

因みに今回使ったデータは、国土交通省の下記を使わせていただきました。ありがとうございます(_ _)

位置参照情報 ダウンロードサービス

 

対策の方針を考えてみる

この対策もいくつか考えられると思いますが、今日は「ズーム値が下がったら(俯瞰したら)マーカーラベルを消す」という方向で対策してみようと思います。

Google Maps API では

1.ズーム値は map.getZoom() メソッドで取得できます。
2.ズームの変更は map.addListener("zoom_changed") リスナで取得できます

一応これをおさえてマーカーの書き換え操作などを加えるとおおむねこの対策ができるようになります。今回はアニメーションを最初だけに限定するというフラグも立てて操作してみました。

今回の対策

これも実際に目で見て確認してみましょう。
デモページ: https://reien.top/blog/test/gmap/marker/2020-11-12-2.html

このページも上と沿うようにズームボタンが並んでいるので押してみると、zoom 13以下でラベル文字が消えるのが判ります。

そしてデモページでズーム値を操作してみるとわかりますが、たとえば zoom 13だとこうなり、文字が消えています。

image.png

対策前のコードと対策後のコード

一応いま急いで書いたざっくりしたサンプルですが、参考までに置いておきます。google Maps のapiキーはご自身で取得したものをお使いください。サイトにおいてコンソール上でそのサイトを許可する必要がありますがそのあたりは下に書いた参考ページが判りやすいです。

対策前

<div id="map" style="width:90%;height:60%"></div>

<script>
    let lists=`"13","東京都","13101","千代田区","131010001002","内幸町二丁目","35.670812","139.754182","0","3"
"13","東京都","13101","千代田区","131010001001","内幸町一丁目","35.670839","139.758119","0","3"
"13","東京都","13101","千代田区","131010002003","霞が関三丁目","35.671825","139.746988","0","3"
"13","東京都","13101","千代田区","131010003000","北の丸公園","35.691555","139.751639","0","1"
   //(省略)
`

let map //ここではmap だけあとでzoomを操作するためにグローバルにおいておきます

//地図を描画する
function initMap(){

    //中心の経緯度
    let lat=35.688069 
    let lng=139.763929

    //経緯度のインスタンスを作る
    let centerlocation = new google.maps.LatLng(
        lat,
        lng
    );

    //DOM要素id map に地図を描画する
    map = new google.maps.Map(document.getElementById("map"), {
        center: centerlocation,
        zoom: 16, //ズーム値
    });
    //経緯度のインスタンスを作る
    let mylocation = new google.maps.LatLng(
        lat,//経度
        lng//経度
    );

    //マーカーを描く
    drawMarkers(map, lists)
}

//データcsvから町名と経緯度を取り出しマーカーを描く
function drawMarkers(map, lists){

    //データcsvから町名と経緯度を取り出す
    let lines=lists.split('\n')//行で分解し配列にする
    //行を回してデータを取り出す
    for(let i=0;i<lines.length;i++){
        let line=lines[i]
        let cols=line.split(',')//列で分解し配列にする

        //マーカーを描く "霞が関一丁目" "35.673944" "139.752558" 
        mkMarker(
            map
            //町名は5番目の列にある
            , cols[5] 
            //latは6番目の列にある
            //単に+やparseFloatでは数値化できなかったので+JSON.parseした
            , +JSON.parse(cols[6]) 
            //lngは7番目の列にある
            , +JSON.parse(cols[7])  
        )
    }
}

//マーカーを描く
function mkMarker(map, name, lat, lng){

    //経緯度のインスタンスを作る
    let mylocation = new google.maps.LatLng(
        lat,//経度
        lng//経度
    );
    //マーカーを描く
    let cityMarker=new google.maps.Marker({
        position: mylocation,//経緯度
        icon: {
            path: google.maps.SymbolPath.CIRCLE,//シンボル円
            scale: 6,          //アイコンサイズ
            fillColor: '#fff',  //塗り潰し色
            fillOpacity: 0.8,   //塗り潰し透過率
            strokeColor: "red", //枠線の色
            strokeWeight: 8,    //枠線の幅
        },
        label: {
            text:  name,           //ラベル文字
            color: 'oraneg',       //文字の色
            fontSize: '12px',      //文字のサイズ
            fontWeight: '900'      //文字の太さ
        },
        draggable: false, //ドラッグしたいならtrue
        map: map, //地図オブジェクト
        animation:  google.maps.Animation.DROP //マーカーアニメーション
    });
}

</script>
<script 
    src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC0BiR5x2hwF3Tj2IQZadRHOLOSznUzXQI&callback=initMap"
    async defer>
</script>

対策後

<div id="map" style="width:90%;height:60%"></div>

<script>
    let lists=`"13","東京都","13101","千代田区","131010001002","内幸町二丁目","35.670812","139.754182","0","3"
"13","東京都","13101","千代田区","131010001001","内幸町一丁目","35.670839","139.758119","0","3"
"13","東京都","13101","千代田区","131010002003","霞が関三丁目","35.671825","139.746988","0","3"
"13","東京都","13101","千代田区","131010003000","北の丸公園","35.691555","139.751639","0","1"
   //(省略)
`

let map //ここではmap だけあとでzoomを操作するためにグローバルにおいておきます
let cityMarkers=[]

//地図を描画する
function initMap(){

    //中心の経緯度
    let lat=35.688069 
    let lng=139.763929

    //経緯度のインスタンスを作る
    let centerlocation = new google.maps.LatLng(
        lat,
        lng
    )

    //DOM要素id map に地図を描画する
    map = new google.maps.Map(document.getElementById("map"), {
        center: centerlocation,
        zoom: 16, //ズーム値
    })

    //ズーム後にzoom値がマーカーを再描画する
    map.addListener("zoom_changed", () => {
        reSetMarkers()
        if(map.getZoom()<14){
            //14未満はラベルなし
            drawMarkers(map, lists, false, false)
        } else {
            //14以上はラベルあり
            drawMarkers(map, lists, true, false)
        }

    })

    //マーカーを描く
    drawMarkers(map, lists, true, true)
}

//マーカーをリセットする
function reSetMarkers(){
    for(let i=0;i<cityMarkers.length;i++){
        cityMarkers[i].setMap(null)
    }
}

//データcsvから町名と経緯度を取り出しマーカーを描く
function drawMarkers(map, lists, labelFlg, animeFlg){

    //データcsvから町名と経緯度を取り出す
    let lines=lists.split('\n')//行で分解し配列にする
    //行を回してデータを取り出す
    for(let i=0;i<lines.length;i++){
        let line=lines[i]
        let cols=line.split(',')//列で分解し配列にする

        //マーカーを描く "霞が関一丁目" "35.673944" "139.752558" 
        mkMarker(
            map
            //町名は5番目の列にある
            , cols[5] 
            //latは6番目の列にある
            //単に+やparseFloatでは数値化できなかったので+JSON.parseした
            , +JSON.parse(cols[6]) 
            //lngは7番目の列にある
            , +JSON.parse(cols[7])
            ,labelFlg
            ,animeFlg
        )
    }
}

//マーカーを描く
function mkMarker(map, name, lat, lng, labelFlg, animeFlg){

    //経緯度のインスタンスを作る
    let mylocation = new google.maps.LatLng(
        lat,//経度
        lng//経度
    );

    // icon設定
    let icon= {
        path: google.maps.SymbolPath.CIRCLE,//シンボル円
        scale: 6,          //アイコンサイズ
        fillColor: '#fff',  //塗り潰し色
        fillOpacity: 0.8,   //塗り潰し透過率
        strokeColor: "red", //枠線の色
        strokeWeight: 8,    //枠線の幅
    }

    //labelフラグによるoption設定分岐
    if(!labelFlg){
        option={
            position: mylocation,//経緯度
            icon: icon,
            draggable: false, //ドラッグしたいならtrue
            map: map, //地図オブジェクト
        }
    } else {
        option={
            position: mylocation,//経緯度
            icon: icon,
            label: {
                text:  name,           //ラベル文字
                color: 'oraneg',       //文字の色
                fontSize: '12px',      //文字のサイズ
                fontWeight: '900'      //文字の太さ
            },
            draggable: false, //ドラッグしたいならtrue
            map: map, //地図オブジェクト
        }
    }

    //マーカーを描く
    let cityMarker=new google.maps.Marker(option);
    //マーカーアニメーションは最初だけにしておく
    if(!!animeFlg){
        cityMarker.setAnimation(google.maps.Animation.DROP)
    } else {
        cityMarker.setAnimation(null);
    }
    //マーカー配列に入れておく
    cityMarkers.push(cityMarker)

}

</script>
<script 
    src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC0BiR5x2hwF3Tj2IQZadRHOLOSznUzXQI&callback=initMap"
    async defer>
</script>

参考

霊園ガイドサイト(ここのCTOやってます)
https://reien.top/

Google maps APIで東京駅を表示する方法(事前準備(APIキー取得)方法など)
https://qiita.com/Jenny1025/items/74935088ced3f70893da

Maps JavaScript API
https://developers.google.com/maps/documentation/javascript/overview
APIキーを取得する
https://developers.google.com/maps/documentation/javascript/get-api-key

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2