Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maps bug: Markers shifting all over the place when switching view angles. Fix?

Google Javascript Maps API 3.5

Basic issue is that if you have a marker that is over a fixed landmark like a fire hydrant in the overhead view, then you switch to 45 degree view, the marker no longer shows on top of the hydrant. And vice versa (position the marker in 45 degree view then switch to overhead).

To reproduce:

See sample here: www.zingjet.com/maptest.html

-Create a basic Google Maps web page with a draggable marker. With initial marker/map position over an area with 45 degree imagery available: (try: 33.501472920248354, -82.01948559679795). I'm not certain it shows this problem for all areas so try that point to start.

-Make sure you are zoomed in near the max and in Satellite view

-Turn off 45 degree imagery

-Position marker over fixed point (corner of sidewalk, house chimney, etc)

-change to 45 degree view.

-Note that marker position is shifted

-Try rotating the 45 degree and see how marker shifts relative to original point on image.

-Switch back to overhead and marker is in original spot.

Why its a problem: Don't know what to trust. What view shows the accurate position for that marker? Can't create web pages that allow people to position markers in one view and see them in another. Major inconsistencies.

like image 220
Fraggle Avatar asked Apr 07 '12 16:04

Fraggle


People also ask

How do I move a marker smoothly on Google Maps?

The transition() and moveMarker() are used to move marker smoothly on click on the Google map.

How do I change the angle on Google Maps?

You can tilt the map in any direction. Press and hold the scroll button. Then, move the mouse forward or backward. Press Shift and scroll forward or backward to tilt up and down.


2 Answers

UPDATED 2

  • demo: http://bit.ly/IhpeBu
        var map, marker, overlay, latlng, zoom = 20;
        function initialize() {
            latlng = new google.maps.LatLng(33.501472920248354, -82.01948559679795);
            var myOptions = {
                zoom : zoom,
                center : latlng,
                tilt : 0,
                mapTypeId : google.maps.MapTypeId.SATELLITE
            }
            map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
            overlay = new google.maps.OverlayView();
            overlay.draw = function() {
            };
            overlay.onRemove = function() {
            };
            overlay.setMap(map);
            marker = new google.maps.Marker({
                position : latlng,
                map : map,
                draggable : true,
                title : "Hello World!"
            });

            google.maps.event.addListener(map, 'zoom_changed', function() {
                zoom = map.getZoom();
            });

            google.maps.event.addListener(map, 'dragend', function() {
                overlay.setMap(map);
            });

            google.maps.event.addListener(marker, 'dragend', function(evt) {
                var tilt = map.getTilt();
                latlng = new google.maps.LatLng(evt.latLng.lat(), evt.latLng.lng());
                if(tilt === 45) {
                    var projection = overlay.getProjection();
                    var latlng2pixel = projection.fromLatLngToContainerPixel(marker.getPosition());

                    var delta = 0;
                    switch(zoom) {
                        case 20:
                            delta = 45;
                            break;
                        case 19:
                            delta = 12;
                            break;
                        case 18:
                            delta = 4;
                            break;
                    }
                    latlng = projection.fromContainerPixelToLatLng(new google.maps.Point(latlng2pixel.x, (latlng2pixel.y + delta )));
                }
            });

            google.maps.event.addListener(map, 'tilt_changed', function() {
                var tilt = map.getTilt();
                if(tilt === 45) {
                    var delta = 0;
                    switch(zoom) {
                        case 20:
                            delta = 65;
                            break;
                        case 19:
                            delta = 32;
                            break;
                        case 18:
                            delta = 16;
                            break;
                    }
                    var projection = overlay.getProjection();
                    var latlng2pixel = projection.fromLatLngToContainerPixel(marker.getPosition());
                    var pixel2latlng = projection.fromContainerPixelToLatLng(new google.maps.Point(latlng2pixel.x, (latlng2pixel.y - delta )));
                    marker.setPosition(pixel2latlng);
                } else {
                    marker.setPosition(latlng);
                }
            });
        }

NOTES: the code above work as follow:

  1. Apply a custom overlay to use the; google.maps.MapCanvasProjection object doc
  2. Find the position in pixel of the marker;
  3. Add to the y ( top = lng ) the 45 degrees ( 45 pixel at zoom 20 ) plus 20 pixel of the marker icon height ( x remain always unvaried since the degrees change is a simple optical illusion ;) );
  4. Convert those pixel position to a valid latlng position;
  5. observe wheter the tilt method change from 0 to 45 and viceversa and act accordingly by setting the new coordinates.
like image 110
Luca Filosofi Avatar answered Oct 19 '22 23:10

Luca Filosofi


What you are going to have to do likely is to hack it. As far as google is concerned there is likely no error and the point on the map "appears" in a different place because the 45 degree view changes the perspective on the map, and thus how a discrete lat long will physically appear on the map (similiar things can happen when the zoom changes). What you need to do is figure out what that delta is between the views and then hook the "tilt_changed" event and adjust your marker appropriately. One good easy way to learn the delta is to hook the "dblclick" event to alert to you the latlng your mouse is on:

google.maps.event.addDomListener(map, 'dblclick', function(MouseEvent){
        alert(MouseEvent.latLng.lat()+" "+MouseEvent.latLng.lng());
    }); 
// make sure you disable the maps default zoom on double click 
//or choose a different event or it will get annoying :)

and then dblclick the screen where the marker "should be" and create a function that adjusts the marker accordingly. In theory you may be able to define a function that works on any angle so that all you have to do is pass every marker's position through the function on tilt_changed. Let me know if this is a good start for you :)

like image 34
Ryan Avatar answered Oct 20 '22 00:10

Ryan