Search code examples
androidcordovagoogle-maps-api-3

Google Maps API v3 in PhoneGap: Circle duplicating and drawing tangent line after move


(This is a split off from my other post I made, Google Maps API v3 in PhoneGap: markers not drawing properly after move) . I've been working on a Google Maps API 3 application on Android using PhoneGap. It should track the users location and mark the location with a marker and a circle around it. I had been developing this on Android 2.3 and it was working fine. I then upgraded to a phone with Android 4.x and it was still working well, I thought.

Then last week I began noticing Google Maps doing some strange things when I moved the Marker and Circle. It would seem to create a duplicate Marker and Circle instead of just moving them. In the other post, I got an answer for the Marker issue, but not for the Circle. Sometimes if I change zoom then the duplicate Circle seems to go away. But also, it occasionally draws some weird tangent line from the top. See images below.

I started noticing this shortly after I received an Android update on my phone to version 4.1.1. Not sure if that's related, I can't find any info about a problem.

I reduced the map and phonegap code to a pretty minimal sample and its still doing it. I'm pretty sure it isn't related to phonegap. I upgraded my phonegap to 2.2 anyway to be sure, but as expected it didn't help. Can anyone tell if I am doing something wrong when moving the circle?

One solution that I tried was to hide the circle before moving it and then show it again after I move it. That seemed to solve the duplicate and tangent issue, but it made the map flash, which is really annoying when you move it every 3 seconds or so. So that doesn't seem like an acceptable solution. Test code is below. Note that I removed my Google Maps API key in test code.

I've also learned that one way to get it to redraw correctly is to drag the map so that no part of any circle is visible. Then when I drag it back so that the circle is visible, it is redrawn as just one correct circle.

Thanks, Eric

<!DOCTYPE HTML>
<html>
<head>
<title>Marker Test</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
    html {height: 100%}
    body {height: 100%; margin:0; padding:0}
    #map_canvas {height: 100%}
</style>
<script type="text/javascript" charset="utf-8" src="js/phonegap.js"></script>
<script type="text/javascript" charset="utf-8" src="http://maps.googleapis.com/maps/api/js?key=YOUR_KEY_HERE&sensor=true"></script>
<script type="text/javascript" charset="utf-8">
    // Wait for PhoneGap to load
    //
    document.addEventListener("deviceready", onDeviceReady, false);

    // globals
    var watchID = null;
    var map = null;
    var myLocationMarker = null;
    var searchCircle = null;

    // PhoneGap is ready
    //
    function onDeviceReady() {
        startGPS();
    }

    function onUnLoad() {
        console.log("clearing watch " + watchID);
        navigator.geolocation.clearWatch(watchID);
    }

function startGPS() {
    console.log("In startGPS");

    var refreshMilliseconds = 5000;
    var options = { frequency: refreshMilliseconds, enableHighAccuracy: true};

    watchID = navigator.geolocation.watchPosition(onGPSSuccess, onGPSError, options);

    // create Google map
    var mapOptions = {
        zoom: 14,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);

    myLocationMarker = new google.maps.Marker({
        title: 'This is me!',
        zIndex: 90,
        optimized: false,
        map:map
    });     

    searchCircle = new google.maps.Circle({
        fillColor: '#c0e4dd',
        strokeColor: '#f15f22',
        fillOpacity: 0.5,
        radius: 1500,
        map:map
    });     
}

var onGPSSuccess = function(p) {
    // get the new coordinates
    var lat = p.coords.latitude;
    var lng = p.coords.longitude;

    console.log("watch ID " + watchID);

    // now that we have the coordinates, we can move the marker and circle on the Google Map
    MoveMarkerAndCircle(lat, lng);
};

var MoveMarkerAndCircle = function(lat, lng) {
    var myLocation = new google.maps.LatLng(lat, lng);
    myLocationMarker.setPosition(myLocation);

//  searchCircle.setVisible(false);
    searchCircle.setCenter(myLocation);
//  searchCircle.setVisible(true);

    map.setCenter(myLocation);  
}

var onGPSError = function() {
    console.log("GPS Error");
};

var GenerateFakeMovement = function() {
    var currentPosition = myLocationMarker.getPosition();
    var newLat = currentPosition.lat() + 0.01;
    var newLng = currentPosition.lng() + 0.01;
    MoveMarkerAndCircle(newLat, newLng);
}
</script>
</head>
<body  style="height:100%;text-align:center" onunload="onUnLoad()">
    <div id="map_canvas" style="width: 100%;height:80%"></div>
    <a href='#' onclick="GenerateFakeMovement();" style="padding-top:5px">MAKE FAKE MOVEMENT</a>
</body>
</html>

2 Circles tangent line broken circles


Solution

  • I hope that I'm doing the right thing by posting this as an "answer". I still have the issue, but I have narrowed my own example down to the point that it seems clear it is an issue with Google Maps API v3 on Android 4.1.1 only. The code for the narrowed down test case is below and no longer involves PhoneGap.

    I've posted the test page online here: http://kcwebprogrammers.com/MarkerTest-NoGps.html

    If you browse there in Windows (Chrome or IE) or with the Internet browser on Android 2.3, then moving the circle works just fine. If you browse to the same page with the Internet browser on Android 4.1.1, then you'll see that the original circle is still visible after the circle is moved, causing two circles. So I've posted the issue to the Google Maps issue list.

    Thanks for the suggestions above. Please let me know if anyone thinks I should do anything different with this post.

    <!DOCTYPE HTML>
    <html>
    <head>
    <title>Marker Test</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style type="text/css">
        html {height: 100%}
        body {height: 100%; margin:0; padding:0}
        #map_canvas {height: 100%}
    </style>
    <script type="text/javascript" charset="utf-8" src="http://maps.googleapis.com/maps/api/js?key=YOUR_KEY_HERE&sensor=true"></script>
    <script type="text/javascript" charset="utf-8">
    
    // globals
    var watchID = null;
    var map = null;
    var myLocationMarker = null;
    var searchCircle = null;
    var myLocation = null;
        
    function onLoad() {
        startGPS();
    }
    
    function onUnLoad() {
        console.log("clearing watch " + watchID);
    }
        
    function startGPS() {
        // simulate getting position from GPS
        myLocation = new google.maps.LatLng(39, -90);
        
        // create Google map
        var mapOptions = {
            zoom: 14,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            center:myLocation
        };
        map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
        google.maps.event.trigger(map, 'resize');
        
        myLocationMarker = new google.maps.Marker({
            title: 'This is me!',
            zIndex: 90,
            optimized: false,
            map:map,
            position: myLocation
        });     
    
        searchCircle = new google.maps.Circle({
            fillColor: '#c0e4dd',
            strokeColor: '#f15f22',
            fillOpacity: 0.5,
            radius: 1500,
            map:map,
            center:myLocation
        });
        // using bindTo instead does not fix the problem
    //  searchCircle.bindTo('center', myLocationMarker, 'position'); //This will set the circle bound to the marker at center
    }
    
    var MoveMarkerAndCircle = function(lat, lng) {
        myLocation = new google.maps.LatLng(lat, lng);
        myLocationMarker.setPosition(myLocation);
        
        // set circle invisible before moving and visible after does fix redraw for 4.1.1
        // but causes some annoying flashing of the circle for 4.1.1 and everything else
    //  searchCircle.setVisible(false);
        searchCircle.setCenter(myLocation);
    //  searchCircle.setVisible(true);
    }
    
    var GenerateFakeMovement = function() {
        var currentPosition = myLocationMarker.getPosition();
        var newLat = currentPosition.lat() + 0.001;
        var newLng = currentPosition.lng() + 0.001;
        MoveMarkerAndCircle(newLat, newLng);
    }
    </script>
    </head>
    <body  style="height:100%;text-align:center" onunload="onUnLoad()" onload="startGPS()">
        <div id="map_canvas" style="width: 100%;height:90%"></div>
        <a href='#' onclick="GenerateFakeMovement();" style="padding-top:5px">MOVE MARKER AND CIRCLE</a>
    </body>
    </html>