Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make a Google map show current location on iOS5 and Opera Mobile?

I've spent quite a bit of time reading up about using the google maps api and have put together the code below. The code first centers on a particular location, and then changes the centre of the map to the users current location - which it highlights with a second marker. It then refreshes the position of the second marker at 5s intervals, without re-centring the map. This works to different extents on different devices and browsers, and I was wondering how I might make it more cross-device compatible.

======================================================================================================================
Device      Browser                      Display map                  Display map marker      Display current location
======================================================================================================================
PC          Chrome                           Yes                           Yes                        Yes (if allowed)
----------------------------------------------------------------------------------------------------------------------
iPhone 3    iOS 5                            Yes                           Yes                        No
----------------------------------------------------------------------------------------------------------------------
Nokia n97   Opera Mobile                     Yes                           Yes                        Yes
----------------------------------------------------------------------------------------------------------------------
Nokia n97   Native symbian browser       Yes, though hybrid map is poor      No      It detects the current location and centres the map there, but doesn't display the image.
----------------------------------------------------------------------------------------------------------------------

I need to host the map on my own site to ensure that it gets rendered correctly with my custom icons, etc.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>mysite - Find your way :)</title>
    <style>
        html, body {
          height: 100%;
          margin: 0;
          padding: 0;
        }

        #map_canvas {
          height: 100%;
        }

        @media print {
          html, body {
            height: auto;
          }

          #map_canvas {
            height: 650px;
          }
        }
    </style>
    <script src="https://maps.googleapis.com/maps/api/js?sensor=true"></script>
    <script>
      var map;
      var current_location;
      var clue_location;
      function initialize()
      {
            var lostLatLong = new google.maps.LatLng(51.1,-0.1);
            var mapOptions = {
              zoom: 19,
              center: lostLatLong,
              mapTypeId: google.maps.MapTypeId.HYBRID,
              streetViewControl: false,
              rotateControl: false,
              zoomControl: true,
              zoomControlOptions: {
                style: google.maps.ZoomControlStyle.LARGE
                }
            }
            map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);

            var image = '/static/images/maps_images/mysite-map-icon-48x48.png';
            clue_location = new google.maps.Marker({
                position: lostLatLong,
                map: map,
                icon: image
            });

            if(navigator.geolocation) 
            {
                navigator.geolocation.getCurrentPosition(function(position) 
                {
                    var current_location_image = '/static/images/maps_images/mysite_location-marker-64x64.png';
                    var newPos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                    current_location = new google.maps.Marker({
                        position: newPos,
                        map: map,
                        icon: current_location_image,
                    });
                    map.setCenter(newPos);
                });
                setTimeout(autoUpdateLocation, 5000);
            }
        }

        function autoUpdateLocation() 
        {
            navigator.geolocation.getCurrentPosition(function(position) 
            {
                current_location.setMap(null);
                var current_location_image = '/static/images/maps_images/mysite_location-marker-64x64.png';
                var newPos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                current_location = new google.maps.Marker({
                    position: newPos,
                    map: map,
                    icon: current_location_image,
                });
            });
            setTimeout(autoUpdateLocation, 5000);
        }

        google.maps.event.addDomListener(window, 'load', initialize);

    </script>

  </head>

  <body>
    <div id="map_canvas"></div>
  </body>
</html>
like image 247
user714852 Avatar asked Nov 03 '22 14:11

user714852


1 Answers

Your code seems to work for me in Opera Mobile 12.1 on Android. However, there are a couple of things which may be causing issues in some cases, for example there are two instances of setTimeout running at the same time doing essentially the same thing. This also goes against the ideal of reusing code as much as possible, so I've tried to simplify your code here:

function initialize() {
    var isFirstTime = true;
    var lostLatLong = new google.maps.LatLng(51.1, -0.1);
    var mapOptions = {
        zoom: 19,
        center: lostLatLong,
        mapTypeId: google.maps.MapTypeId.HYBRID,
        streetViewControl: false,
        rotateControl: false,
        zoomControl: true,
        zoomControlOptions: {
            style: google.maps.ZoomControlStyle.LARGE
        }
    };
    var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
    var image = '/static/images/maps_images/mysite-map-icon-48x48.png';
    var clue_location = new google.maps.Marker({
        position: lostLatLong,
        map: map,
        icon: image
    });

    function autoUpdateLocation() {
        navigator.geolocation.getCurrentPosition(function(position) {
            // Remove marker if necessary
            if (!isFirstTime && current_location) {
                current_location.setMap(null);
            }

            // Get new location
            var current_location_image = '/static/images/maps_images/mysite_location-marker-64x64.png';
            var newPos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
            var current_location = new google.maps.Marker({
                position: newPos,
                map: map,
                icon: current_location_image
            });

            // Set centre first time only
            if (isFirstTime && map) {
                map.setCenter(newPos);
                isFirstTime = false;
            }
        });
    }

    if (navigator.geolocation) {
        setInterval(autoUpdateLocation, 5000);
    }
}

google.maps.event.addDomListener(window, 'load', initialize);

Other notes:

  • I've replaced setTimeout with setInterval which is more appropriate for repeated tasks.

  • Put everything inside the initialize() function to keep things out of the global namespace.

  • Removed ending commas on the last item in an object.

  • current_location variable does not need to be declared outside the autoUpdateLocation() function.

It can probably be improved further but this should be a bit more robust. Let me know if you're still having problems.

like image 183
tagawa Avatar answered Nov 09 '22 08:11

tagawa