web-dev-qa-db-ja.com

html5とjavascriptを介してユーザーのジオロケーションを取得する

Html5 geolcation apiを介してユーザーのジオロケーションを取得しようとしていますが、次のスニペットを使用しています。

if (navigator.geolocation) {
    var timeoutVal = 10 * 1000 * 1000;
    navigator.geolocation.getCurrentPosition(
      displayPosition, 
      displayError,
      { enableHighAccuracy: true, timeout: timeoutVal, maximumAge: 0 }
    );
  }
  else {
     // DO SOME STUFF HERE
  }


  function displayPosition(position) {

    // configuration
    var myZoom = 12;
    var myMarkerIsDraggable = true;
    var myCoordsLenght = 6;
    var defaultLat = position.coords.latitude;
    var defaultLng = position.coords.longitude;
    document.getElementById('latitude').value = defaultLat;
    document.getElementById('longitude').value = defaultLng;
    /*
      1. creates the map
      2. zooms
      3. centers the map
      4. sets the map’s type
    */
    var map = new google.maps.Map(document.getElementById('canvas'), {
      zoom: myZoom,
      center: new google.maps.LatLng(defaultLat, defaultLng),
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });


    });
    // centers the map on markers coords
    map.setCenter(myMarker.position);
    // adds the marker on the map
    myMarker.setMap(map);
  }

  function displayError(error) {
    var errors = { 
      1: 'Permission denied',
      2: 'Position unavailable',
      3: 'Request timeout'
    };
    alert("Error: " + errors[error.code]);
  }
});

上記のアプローチの問題点は、使用が難しいと感じているユーザーがほとんどいないことです。まれに、許可ではなく拒否をクリックして、画面を見つめ続けています。したがって、ユーザビリティの観点から、良いアプローチは次のようになると思います。

  1. 彼らに許可を求めてください。

  2. 3秒間待ちます。[拒否]をクリックするか、応答しない場合は、IPを使用して地図上に地理を表示します。

上記のスニペットの2番目のステップを実行するにはどうすればよいですか。教えてください、ありがとう!ただし、処理するためのより良い方法は何でしょうか

14
whatf

これがスクリプトです( geolocator.js )少し前に書き、最近更新しました。

更新:Geolocatorv2がリリースされました。

特徴:

  • HTML5ジオロケーション(ユーザーの許可による)
  • IPによる場所
  • ジオコーディング(住所からの座標)
  • 逆ジオコーディング(座標からの住所検索)
  • 完全な住所情報(通り、町、近所、地域、国、国コード、郵便番号など...)
  • フォールバックメカニズム(HTML5ジオロケーションからIPジオルックアップへ)
  • 地理的位置を見る
  • 距離行列と期間を取得する
  • 2つの地理的ポイント間の距離を計算します
  • タイムゾーン情報を取得する
  • クライアントIPを取得する
  • Googleローダーをサポートします(Googleマップを動的にロードします)
  • Googleマップを動的に作成します(マーカー、情報ウィンドウ、自動調整ズーム付き)
  • ノンブロッキングスクリプトの読み込み(外部ソースはページの読み込みを中断することなくオンザフライで読み込まれます)

ライブデモ を参照してください。
APIドキュメント を参照してください。

Geolocator Example Screenshot

使用法:

var options = {
    enableHighAccuracy: true,
    timeout: 6000,
    maximumAge: 0,
    desiredAccuracy: 30, // meters
    fallbackToIP: true, // get location by IP if geolocation fails or rejected
    addressLookup: true, // requires Google API key
    timezone: true, // requires Google API key
    map: "my-map" // creates a Google map. requires Google API key
};
geolocator.locate(options, function (err, location) {
    console.log(err || location);
});

出力例:

{
    coords: {
        latitude: 37.4224764,
        longitude: -122.0842499,
        accuracy: 30,
        altitude: null,
        altitudeAccuracy: null,
        heading: null,
        speed: null
    },
    address: {
        commonName: "",
        street: "Amphitheatre Pkwy",
        route: "Amphitheatre Pkwy",
        streetNumber: "1600",
        neighborhood: "",
        town: "",
        city: "Mountain View",
        region: "Santa Clara County",
        state: "California",
        stateCode: "CA",
        postalCode: "94043",
        country: "United States",
        countryCode: "US"
    },
    formattedAddress: "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
    type: "ROOFTOP",
    placeId: "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
    timezone: {
        id: "America/Los_Angeles",
        name: "Pacific Standard Time",
        abbr: "PST",
        dstOffset: 0,
        rawOffset: -28800
    },
    flag: "//cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/flags/4x3/us.svg",
    map: {
        element: HTMLElement,
        instance: Object, // google.maps.Map
        marker: Object, // google.maps.Marker
        infoWindow: Object, // google.maps.InfoWindow
        options: Object // map options
    },
    timestamp: 1456795956380
}
16

次に、次のようなgeo ipapiを使用します。

http://freegeoip.net/static/index.html

3
cliffbarnes

わかりました。これはコードの答えではなく、ユーザーエクスペリエンスの答えです。

UXの観点から、最初に目立つのは、ブラウザーをトリガーして許可を求める前に提供している情報が不足していることです。

許可を求められる画面の「場所」を示すスクリーンショット(大きな矢印が付いている)を示す、ある種のオーバーレイボックスを用意することをお勧めします。また、その機会を利用して、許可を拒否したり、たとえば10秒以内に許可を受け入れなかった場合(つまり、プロンプトバーを無視した場合)に何が起こるかを伝えることができます。

IPの場所をデフォルトで表示しないことをお勧めします。これは、基本的に「私がどこにいるかを通知することに同意しない」と言っている可能性があるためです。次に、彼らがどこにいるかの大きな地図を表示します。これは、[拒否]をクリックした数人の人々を驚かせる可能性があります。その上、それは非常に不正確かもしれません。

「許可を求めないで許しを求める」という考えは、Biz devでは機能するかもしれませんが、UIでは機能しない可能性があります。

本当に高精度が必要かどうかを自問します。高精度はユーザーのバッテリーを消耗し、時間がかかり、特にそれらがどこにあるかを大まかに見つけるためだけに必要な場合は、それ以上の価値がない可能性があるためです。必要に応じて、後でいつでも再度呼び出して、より正確に読み取ることができます。

拒否または許可をクリックしない場合にタイムアウトするという概念は、setTimeoutを使用して実現できます。したがって、オーバーレイボックスで[OK、[許可]をクリックする準備ができました]をクリックしたら、タイムアウトを開始し、最終的にタイムアウトになる場合は、上記の手順で行うように指示したことを実行します。

この方法を使用すると、ユーザーに許可または拒否(無視)のいずれかを強制します。どちらの方法でも、制御を法廷に戻し、ユーザーに完全な情報を提供し続けます。

これはコード固有の答えではありませんが、JSからは、「コード実装のヘルプ」が実際にはここでの問題ではないことは明らかです。これがあなたのユーザーエクスペリエンスについてもう少し考えさせてくれることを願っています。

2
Rick Hurst

タイムアウトが発生した場合、またはユーザーがリクエストを拒否した場合は、ニューヨーク州ニューヨーク(40.7142、-74.0064)のようなデフォルトの場所を設定します。ユーザーがリクエストを拒否した場合、ユーザーはあなたが自分の場所を知らないことも期待する必要があるため、わかりやすいデフォルトを選択することが次善の策です。

コードを変更せずにデフォルトを使用するには、次の2つの場所でdisplayPosition({coords: {latitude: 40.7142, longitude: -74.0064}})を呼び出すことで実現できます。

if (navigator.geolocation) {
    var timeoutVal = 10 * 1000 * 1000;
    navigator.geolocation.getCurrentPosition(
        displayPosition, 
        displayError,
        { enableHighAccuracy: true, timeout: timeoutVal, maximumAge: 0 }
    );
}
else {
    displayPosition({coords: {latitude: 40.7142, longitude: -74.0064}})
}
....
function handleError(error){
    switch(error.code)
    {
        case error.PERMISSION_DENIED: alert("User did not share geolocation data");break;  
        case error.POSITION_UNAVAILABLE: alert("Could not detect current position");break;  
        case error.TIMEOUT: alert("Retrieving position timed out");break;  
        default: alert("Unknown Error");break;  
    }
    displayPosition({coords: {latitude: 40.7142, longitude: -74.0064}});
}

On http://nearbytweets.com ユーザーの場所を見つけるために関数の「キュー」を使用し、そのうちの1つが有効な場所を見つけるまでキューをループします。最後の関数はニューヨーク州ニューヨークを返します。これは、他のすべての試行が失敗したことを意味します。少し変更されたコードのサンプルを次に示します。

var position_finders = [                                                                                                                                                                                                              
    function () {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(check_position, check_position);
            return;
        }   
        check_position();
    },  
    function () {
        check_position(JSON.parse(localStorage.getItem('last_location')));
    },  
    function () {
        $.ajax({
            url: 'http://www.google.com/jsapi?key=' + google_api_key,
            dataType: 'script',
            success: check_position
        }); 
    },  
    function () {
        check_position({latitude: 40.7142, longitude: -74.0064}, true);
    }   
],

check_position = function (pos, failed) {
    pos = pos || {}; 
    pos = pos.coords ? 
        pos.coords :
        pos.loader ?
        pos.loader.clientLocation :
        pos;

    if (typeof pos.latitude === 'undefined' || typeof pos.longitude === 'undefined') {
        position_finders.shift()();
        return;
    }   

    localStorage.setItem('last_location', JSON.stringify(pos));

    // using your code, I would call this:
    displayPosition(pos);
};

check_position();

各position_Finderの機能は次のとおりです。

  1. Navigator.geolocationを試行します。
  2. LocalStorageから最後の場所をプルしようとします
  3. Google Loader を使用して、IP経由で場所を検索します。
  4. ニューヨーク州ニューヨークを使用
0
Brian Cray

これは助けになるかもしれません: http://jsfiddle.net/sandesh2302/FghFZ/ 私はこれを自分のものに使用しました、それはうまくいきました。

例:

    <!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />    
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=true"></script>    

    <script type="text/javascript">
      function getLocation(){
        navigator.geolocation.getCurrentPosition(handleSuccess,handleError);
      }

      function initiate_watchlocation() {  
        if(watchProcess == null){
          watchProcess = navigator.geolocation.watchPosition(handleSuccess,handleError);
        }
      } 

      function stop_watchlocation() {  
        if(watchProcess != null){
          navigator.geolocation.clearWatch(watchProcess);
        }
      } 

      function handleSuccess(position){
        drawMap(position);
      }

      function handleError(error){
        switch(error.code)
        {
          case error.PERMISSION_DENIED: alert("User did not share geolocation data");break;  
          case error.POSITION_UNAVAILABLE: alert("Could not detect current position");break;  
          case error.TIMEOUT: alert("Retrieving position timed out");break;  
          default: alert("Unknown Error");break;  
        }
      }


      function drawMap(position) {
        var container = $('#map_canvas');
        var myLatLong = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
        var mapOptions = {
          center: myLatLong,
          zoom: 12,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var map = new google.maps.Map(container[0],mapOptions);
        container.css('display','block');
        var marker = new google.maps.Marker({ 
          position: myLatLong,
          map:map,
          title:"My Position (Accuracy of Position: " + position.coords.accuracy + " Meters), Altitude: " 
            + position.coords.altitude + ' Altitude Accuracy: ' + position.coords.altitudeAccuracy
        });
      }

      function drawStaticMap(position){
        var container = $('#map_canvas');
        var imageUrl = "http://maps.google.com/maps/api/staticmap?sensor=false&center=" + position.coords.latitude + "," +  
                    position.coords.longitude + "&zoom=18&size=640x500&markers=color:blue|label:S|" +  
                    position.coords.latitude + ',' + position.coords.longitude;  

        container.css({
          'display':'block',
          'width' : 640
        });
        $('<img/>',{
          src : imageUrl
        }).appendTo(container);
      } 
    </script>
  </head>
  <body >
    <button id="getLocation">Find My Location</button>
    <div style="text-align:center">
      <button id="initWatch">Put Watch on Your Position</button>
      <button id="stopWatch">Stop Position Watching</button>
    </div>
    <div id="map_canvas" ></div>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>



  </body>
</html>
0
StackedFlow

このオンラインサービスを使用して、簡単にlatlngを取得できます。

http://dev.maxmind.com/geoip/javascript

タイムアウトに関しては、ブラウザのアクセス許可メカニズムに干渉する方法はないと思います(たとえば、一定の秒数後にそのアクセス許可ポップアップを閉じるなど)-私は喜んで間違っていることが証明されますが。タイマーを設定し、3秒後に、IPベースのジオロケーションを取得してマップを設定します(または、3秒後にページを更新し、HTML5ではなくIPベースのジオをトリガーするCookieを設定します)。 geoですが、私に言わせれば、それは少し上です)。

次に、許可が与えられた場合、HTML5ジオロケーション(はるかに正確なはずです)でマップを更新します。 IPジオフォールバックを関数にカプセル化して、HTML5ジオロケーションがない場合や拒否された場合に使用することもできます。

ここにフィドルがあります: http://jsfiddle.net/mfNCn/1/

これがフィドルからのラフカットです:

<script src="http://j.maxmind.com/app/geoip.js" charset="ISO-8859-1" type="text/javascript"></script>
...
var time_perm = window.setTimeout(get_by_ip, 3000);
...
function get_by_ip() {
    var lat = geoip_latitude();
    var lng = geoip_longitude();
    map_it(lat, lng);
}
...
function map_it(lat,lng) {
    // build your map here
}

(コードチャンク全体がかなり長いので、ここに置くのをためらっています。残りの部分と完全な実装については、フィドルを確認してください)

0
hejhi
0
Shushant