Получение геолокации пользователей через html5 и javascript - программирование

Получение геолокации пользователей через 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]);
  }
});

Проблема с вышеприведенным подходом заключается в том, что мало кто из пользователей затруднился в использовании. Мало того, они нажали Отклонить вместо Разрешить и продолжать смотреть на экран. Поэтому, с точки зрения удобства использования, я считаю, что хороший подход:

  • Спросите у них разрешения.

  • Подождите 3 секунды, если они нажмут кнопку deny или не ответят, используйте IP, чтобы показать геоляцию на карте.

Как я могу выполнить второй шаг в моих предыдущих фрагментах. Пожалуйста дайте мне знать, спасибо! Однако, что было бы лучшим способом справиться с

4b9b3361

Ответ 1

Вот script ( geolocator.js) Я написал некоторое время назад и недавно обновился.

Обновление: выпущен Geolocator v2.

Особенности:

  • Геолокация HTML5 (по разрешению пользователя)
  • Местоположение по IP
  • Геокодирование (координаты с адреса)
  • Обратное геокодирование (поиск адреса из координат)
  • Полная адресная информация (улица, город, окрестности, регион, страна, код страны, почтовый индекс и т.д.).
  • Механизм возврата (от HTML5-геолокации до поиска IP-geo)
  • Смотреть географическое положение
  • Получить матрицу расстояний и длительность
  • Рассчитать расстояние между двумя географическими точками
  • Получить информацию о часовом поясе
  • Получить клиентский IP-адрес
  • Поддержка Google Loader (динамически загружает Карты Google).
  • Динамически создает Карты Google (с маркером, информационным окном, автоматически настроенным масштабированием)
  • Неблокирующая script загрузка (внешние источники загружаются "на лету" без прерывания загрузки страницы)

Смотрите живая демонстрация.
См. документация по API.

Скриншот примера геолокатора

Использование:

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
}

Ответ 3

Хорошо, так что это не ответ на код, более ответ на User Experience.

С точки зрения UX, первое, что выделяется, - это отсутствие информации, которую вы предлагаете, прежде чем вы запустите браузер, чтобы попросить разрешения.

Я предлагаю, чтобы у вас была какая-то оверлейная рамка, показывающая снимок экрана (с большой стрелкой на нем), демонстрирующий "where" на экране, на которое они будут запрошены разрешения. Также вы можете воспользоваться этой возможностью, чтобы рассказать им, что произойдет, если они откажут в разрешении или не смогут принять его в течение 10 секунд (т.е. Где они игнорируют строку подсказки).

Я предлагаю вам не показывать по умолчанию местоположение IP-адреса, потому что они по существу "могут сказать". Я не согласен дать вам знать, где я. Затем вы показываете большую карту, где они есть, что может вызвать уродство нескольких людей, которые отказались! Кроме того, это может быть очень неточно.

Идея "не просить разрешения просить прощения", может работать в Biz dev, но не в пользовательском интерфейсе, поскольку они просто не возвращаются.

Я бы спросил, действительно ли вам нужна высокая точность, потому что он будет сбрасывать аккумулятор пользователя, уходит больше времени и, возможно, не даст вам больше шансов для вашего доллара, особенно если вам нужно только выяснить, где они находятся, Вы всегда можете позвонить ему позже для более точного чтения, если вам нужно.

Концепция тайм-аута, если они не нажимают deny или allow, может быть достигнута с помощью setTimeout. Поэтому, как только они нажмут "ОК, я готов щелкнуть мышью" в окне оверлея, начните таймаут, и если он закончит таймаут, то сделайте то, что вы сказали им, что сделаете на этом шаге.

Используя этот метод, вы вынуждаете пользователя либо разрешать, либо отклонять (игнорировать), так как он возвращает управление в ваш суд и полностью информирует пользователя.

Хотя это не ответ на конкретный код, из вашего JS ясно, что "помощь по реализации кода" на самом деле не проблема. Я надеюсь, что если ничто другое не заставит вас немного подумать о вашем пользовательском опыте.

Ответ 5

Это может помочь: 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>

Ответ 6

Вы можете использовать эту онлайн-услугу, чтобы легко получить лат:

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

Что касается тайм-аута, я не думаю, что есть способ вмешаться в механизм разрешения браузеров (например, закрыть это всплывающее окно разрешения через определенное количество секунд), хотя я бы с радостью оказался ошибочным. То, что вы могли бы сделать, это установить таймер и через три секунды получить геолокацию на основе IP и установить для нее карту (или обновить страницу через 3 секунды и установить cookie, который запускает геоданные на основе IP, а не HTML5 geo, но это немного выше, если вы спросите меня).

Затем, если они дадут разрешение, он обновит карту с помощью геолокации HTML5 (что должно быть намного точнее). Вы также можете инкапсулировать резерв IP geo в функцию и использовать ее, если у них нет геолокации HTML5, или они попадают в deny.

Здесь скрипка: 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
}

(я стесняюсь поставить здесь весь фрагмент кода, поскольку он довольно длинный, поэтому проверьте скрипт для остальных и полную реализацию)

Ответ 7

Если есть тайм-аут или пользователь отклоняет запрос, я бы установил местоположение по умолчанию, такое как Нью-Йорк, Нью-Йорк (40.7142, -74.0064). Если пользователь отказывает в запросе, он также должен ожидать, что вы не узнаете их местоположение, поэтому выбор разумного значения по умолчанию - это лучшая вещь.

Использование значения по умолчанию без изменения кода может быть выполнено путем вызова 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}});
}

Вкл http://nearbytweets.com Я использую "очередь" функций для поиска местоположения пользователя, прокручивая очередь, пока один из них не найдет действительное местоположение. Последняя функция возвращает Нью-Йорк, штат Нью-Йорк, что означает, что все другие попытки потерпели неудачу. Здесь образец кода слегка изменился:

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:

  • Прогоняет навигатор .geolocation.
  • Попытка вытащить свое последнее местоположение из localStorage
  • Использует Google Loader, чтобы найти местоположение через I.P.
  • Использование Нью-Йорка, Нью-Йорк

Ответ 8

С точки зрения пользовательского интерфейса, я бы выполнил следующие шаги:

A) показать красивое текстовое поле, объясняющее, что произойдет дальше (I.e. "браузер попросит вас предоставить разрешение", "разрешить клик" и т.д.) и попросить нажать кнопку для продолжения B) отобразить карту, как сейчас,