Webフォーム 地図から住所入力

スマートフォンやタプレットなどの携帯端末を使う機会が増えているが、ガラケーに比べりゃ簡単になったとはいえ、画面を触りまくる文字入力は面倒というか上手くできなくてイライラ。できるだけ文字入力はしたくない。じゃあ、携帯端末で文字入力しなきゃならないのって何だっけ?と思い返したらウェブサイトのフォームってことが多い気がする。(「がとらぼ」の中の人の使用状況では)
中でも住所入力は面倒かな。
最近はこの手の情報の入力はオートコンプリート機能も使える場合もあるが、フォームによっては対応してなかったり酷いのになると正しい項目に入らなかったりで余計にイラッ。 そこで、できるだけ文字入力しなくてすむように、地図で自分の家をクリックして住所入力するフォームの非常に簡単なのを作ってみた。

この記事はウェブサイトの運営者向けなので念のため。

注意点
Google Maps APIを使うのでAPIのキーが必要。
HTTPSのページ(サイト)でないと使えない。(Google Maps APIの仕様)
下の例は簡単にするため日本の一般的な住所の形式にのみ対応
手抜きなのでページを開いた際にいきなり現在地取得の許可を求められる方式

地図から住所入力

DEMOページ

使い方

  1. フォームのページを開いたら現在地を取得しようとする。
  2. 現在地が取得できない環境なら日本橋の地図とマーカーが表示される。5へ。
  3. 所得した現在地が地図上のマーカーで表示され、フォームにその地点の住所が入力される。
  4. マーカーの位置が自宅であるなら8へ。
  5. 位置が違うなら地図を操作して正しい自宅などをクリック(タッチ)。
  6. 地図をクリックした場所にマーカーが表示され、フォームにその地点の住所が入力される。
  7. マーカーの位置が自宅でないなら5に戻る。正しければフォームに入力された住所を確認
  8. フォームの住所が正しいなら入力完了
  9. フォームの住所が正しくないなら修正(これは手入力するしかない)

つまり、「現在地」が自宅ならラッキー、そうでないなら地図で自宅をクリック。フォームに表示された住所が正しければ良かったね。正しくなければ、あきらめて自分で直せ。こんな感じ。

HTMLのソース
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <title>悪いインターネット | フォームで地図から住所入力</title>
</head>
<body>
    <h1>フォームで地図から住所入力</h1>

    <ul>
        <li>緯度: <span id="lat"></span></li>
        <li>経度: <span id="lng"></span></li>
        <li>住所: <span id="address"></span></li>
    </ul>
    <div style="width:calc(100% - 20px); height:450px; margin:10px;" id="map"></div>

    <p>上の地図でクリックした地点の住所が下に入力されます。<br />
    その後、必要に応じて修正して下さい。</p>

    <form action="./hoge.php" method="post">
        <p>郵便番号: <input id="postal" type="text" name="postal-code" size="8"></p>
        <p>都道府県: <input id="addr1" type="text" name="address-level1" size="8"></p>
        <p>市区町村: <input id="addr2" type="text" name="address-level2" size="24"></p>
        <p>番地・建物名 (1行目): <input id="addr3" type="text" name="address-line1" size="48"></p>
        <p>番地・建物名 (2行目): <input id="addr4" type="text" name="address-line2" size="48"></p>
        <p><input type="submit" value="送信"><input type="reset" value="リセット"></p>
    </form>
    <p>↑の送信ボタンはダミーです。</p>

    <script src="//maps.google.com/maps/api/js?key=自分のウェブサイトで使用できるAPIキー"></script>
    <script src="./map.js"></script>
</body>
</html>

javascriptのソース  (上のHTMLでは最後の方のmap.js)
//グローバル変数 日本橋の座標
lng = 139.77450370788574;
lat = 35.68421096423828;

// GeoLocation APIに対応している場合
if( navigator.geolocation ){
    //現在位置取得
    navigator.geolocation.getCurrentPosition(getPosition);
}

function getPosition(position){
    lat = position.coords.latitude;
    lng =  position.coords.longitude;
}

google.maps.event.addDomListener(window, 'load', function() {
    var objMarker;
    var objMap;
    var latlng = new google.maps.LatLng(lat, lng);

    var optMap = {
        zoom: 15,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scaleControl: true
    };
    objMap = new google.maps.Map(document.getElementById('map'), optMap);

    //初期位置の住所取得
    getAddress(latlng);

    //マーカー
    objMarker = new google.maps.Marker({
        position: latlng,
        map: objMap
    });

    // マップクリックイベントを追加 
    google.maps.event.addListener(objMap, 'click', function(e) {
        // ポジションを変更 
        objMarker.position = e.latLng;
        // マーカーをセット 
        objMarker.setMap(objMap);
        // 地図の中心をマーカーの位置に変更 
        objMap.setCenter(e.latLng);
        // 住所取得
        getAddress(e.latLng);
    });
});

function getAddress(position){
    var geocoder = new google.maps.Geocoder();
    var postalcode = "";
    var level1 = "";
    var locality = "";
    var sublocality = "";
    var level2 = "";
    var level3 = "";
    var level4 = "";
    var level5 = "";
    var levelPlus1 = "";
    var levelPlus2 = "";
    var premise = "";
    var street = "";

    //緯度/経度書き出し
    document.getElementById( 'lat' ).innerHTML = position.lat() ;
    document.getElementById( 'lng' ).innerHTML = position.lng() ;

    geocoder.geocode({'latLng': position, 'language': 'ja'}, function(results, status) {
        if(status==google.maps.GeocoderStatus.OK){
            if (results[1]) {
                //郵便番号+住所書き出し
                document.getElementById( 'address' ).innerHTML = results[0].formatted_address.replace(/^日本, /, '');

                for(var i=0;i < results[0].address_components.length; i++){
                    for(var j=0; j < results[0].address_components[i].types.length; j++){
                        if(results[0].address_components[i].types[j] == "postal_code"){
                            postalcode = results[0].address_components[i].short_name;
                        }
                        if(results[0].address_components[i].types[j] == "administrative_area_level_1"){
                            level1 = results[0].address_components[i].short_name;
                        }
                        if(results[0].address_components[i].types[j] == "locality"){
                            locality = results[0].address_components[i].short_name;
                        }
                        if(results[0].address_components[i].types[j] == "sublocality"){
                            sublocality = results[0].address_components[i].short_name;
                        }
                        if(results[0].address_components[i].types[j] == "sublocality_level_2"){
                            level2 = results[0].address_components[i].short_name;
                        }
                        if(results[0].address_components[i].types[j] == "sublocality_level_3"){
                            level3 = results[0].address_components[i].short_name;
                        }
                        if(results[0].address_components[i].types[j] == "sublocality_level_4"){
                            level4 = results[0].address_components[i].short_name;
                        }
                        if(results[0].address_components[i].types[j] == "sublocality_level_5"){
                            level5 = results[0].address_components[i].short_name;
                        }
                        if(results[0].address_components[i].types[j] == "premise"){
                            premise = results[0].address_components[i].short_name;
                        }
                    }
                }
                //番地を繋ぐハイフン2つ
                if ( level3 !== ""  && level4 !== ""){
                    levelPlus1= "−";
                }
                if ( level4 !== ""  && level5 !== ""){
                    levelPlus2= "−";
                }

                //番地
                street = level2 + level3 + levelPlus1 +  level4 + levelPlus2 + level5;

                //この下のフォーム住所書き出し innerHTMLではなくvalueなので注意
                document.getElementById( 'postal' ).value = postalcode;
                document.getElementById( 'addr1' ).value = level1;
                document.getElementById( 'addr2' ).value = locality + " " + sublocality;
                document.getElementById( 'addr3' ).value = street;
                document.getElementById( 'addr4' ).value = premise;
            } else {
                document.getElementById( 'address' ).innerHTML = '取得できませんでした';
            }
        } else {
            document.getElementById( 'address' ).innerHTML = 'エラー: 取得できませんでした';
        }
    });
}

フォームの「送信」ボタンを押した時に実行されるスクリプト(上のソースではhoge.php)についてはこの記事では関係ないので省略。

住所を全部求める方は凄く簡単だけど、都道府県や市町村、番地など個別に取るのはjavascriptだと意外と大変。グルングルン回して取るという方法。ここは気に入らないので何か良い方法ないかしら。

API使ってるとはいえ、こんな簡単にできていいのだろうか。

ところで、世の中には地図が苦手な人も結構多いんだよね・・ボソッ


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です