Embed Google Maps on page without overriding iPhone scroll behavior
Asked Answered
C

1

9

I'm working on optimizing a site for mobile. We have a Location page that includes info about a location and a map of the location via the Google Maps API. (v2 - I know it's deprecated but I haven't justified the time to upgrade, "if it ain't broke..") I want to use a single column layout with basic information followed by the map followed by more information.

Now when I use my finger to scroll down the mobile page on an iPhone, once I get to the map, the page scrolling is overridden and the map starts panning. The only way for me to scroll farther down the page is to put my finger above or below the map, assuming such space is available. If I disable map dragging, then when I start scrolling down and get to the map it doesn't pan but the page doesn't scroll either. I would like to treat the map as a static image that I can scroll past, but still allow the zoom buttons and allow the map to be redrawn with directions through a select field I have coded, so a literal static image is not a solution.

I found this post that required similar functionality, but it's using v3. I think all I need to do is "add touch events to the map container," but I'm not familiar with that part of javascript, and what I have below does not allow normal scrolling. Do I need to bite the bullet on v3, or do I have a bug on adding touch events that has a simple javascript correction to do what I want?

function initialize() {
  if (GBrowserIsCompatible()) {
    map = new GMap2(document.getElementById("map_canvas"));
    geocoder = new GClientGeocoder();
  }
}

function showAddress(address, zoom) {
//clipped... this part works fine
}

//These three lines create a map that my finger pans
initialize(); 
showAddress("[clipped.. street, zip code]");
map.addControl(new GSmallZoomControl3D());

//This stops the map pan but still prevents normal page finger scrolling
map.disableDragging();

//If done right could this allow normal page finger scrolling??
var dragFlag = false;
map.addEventListener("touchstart", function(e){
   dragFlag = true;
   start = (events == "touch") ? e.touches[0].pageY : e.clientY; 
},true);
map.addEventListener("touchend", function(){ 
dragFlag = false; 
}, true);
map.addEventListener("touchmove",function(
if ( !dragFlag ) return;
end = (events == "touch") ? e.touches[0].pageY : e.clientY;   
window.scrollBy( 0,( start - end ) ); 
}, true);

I have also tried replacing map.addEventListener with document.getElementById("map_canvas").addEventListener or document.addEventListener to no avail.

Cq answered 23/9, 2011 at 21:8 Comment(4)
The map is within an iframe hosted at Google and unless there is something Google let's you toggle with JavaScript, you're probably out of luck. API v2 has been deprecated so if you found something using version 3 that works, why not make the switch? API v3 has many more features and is easier to use, IMHO, anyway. (No more API Key required for one!)Salvatoresalvay
I started looking into v3 before posting this. No API key is nice but we need to use the geocoding function which looks like it does requires an API key and it looks like its response is more complex than on v2, and we have a few other pages which use it as well. Basically I'm trying to avoid a few hours of recoding for v3 with a quick v2 fix, but if that's not possible I'll give in and do the sensible upgrade.Cq
I've now upgraded to v3 but cannot get the touch events to work. I'm poring over my javascript for errors but I'm having trouble getting the touch events to respond to anything at all.Cq
Your best bet would be to just delete this entire question and start a new question for this new issue.Salvatoresalvay
C
18

I solved it by upgrading to v3 and then detecting a basic javascript error in my use of the code from the solution linked above. The key was

start = (events == "touch") ? e.touches[0].pageY : e.clientY; 

The user must have been setting the events variable somewhere outside the presented code, since it looks like the matching assignment is for touch events and the else assignment is for key events. But since I didn't have an events variable it was defaulting to the wrong assignment. I simply changed mine to start = e.touches[0].pageY (and did the same for the touchend event) and now everything works.

However, I switched back to v2 to see if it would work with that javascript error corrected, and it did not. So it looks like I did not waste any time upgrading to v3, neither in figuring out this specific solution nor in setting myself up for future compatibility.

In conclusion, if you want to embed Google Maps on a mobile page and be able to scroll past it, you need to use API v3, disable dragging, and add touch events. I made a few minor tweaks to my code as well, presented here for any who may benefit in the future:

function initialize() 
{
    geocoder = new google.maps.Geocoder();
    var myOptions = {
       mapTypeId: google.maps.MapTypeId.ROADMAP             
    };

    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}

function showAddress(address, zoom) 
{
   if (geocoder) 
   {
      geocoder.geocode( { 'address': address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            map.setCenter(results[0].geometry.location);
            map.setOptions( { zoom: zoom });
            var marker = new google.maps.Marker({
                map: map,
                position: results[0].geometry.location
            });
         }
      });
   }
}

initialize(); 
showAddress("'.$geocode_address.'");

map.setOptions( { draggable: false });

var dragFlag = false;
var start = 0, end = 0;

function thisTouchStart(e)
{
    dragFlag = true;
    start = e.touches[0].pageY; 
}

function thisTouchEnd()
{
    dragFlag = false;
}

function thisTouchMove(e)
{
    if ( !dragFlag ) return;
    end = e.touches[0].pageY;
    window.scrollBy( 0,( start - end ) );
}

document.getElementById("map_canvas").addEventListener("touchstart", thisTouchStart, true);
document.getElementById("map_canvas").addEventListener("touchend", thisTouchEnd, true);
document.getElementById("map_canvas").addEventListener("touchmove", thisTouchMove, true);
Cq answered 26/9, 2011 at 15:27 Comment(3)
Note: I know I could simply include draggable: false in the initial options, but that initialize() function is a generic function that I also use for other maps that I want to be dragged. map.setOptions is a way to customize each map after creation.Cq
A note for the people using jQuery: you need to retrieve the touches attribute from the original event, not the jQuery-wrapped event. For example: $("#map_canvas").on("touchstart", function(e) { dragFlag = true; start = e.originalEvent.touches[0].pageY; });Philomena
solves problem with scrolling on a full page map on a Windows Phone 8.1 device, thanks !Kktp

© 2022 - 2024 — McMap. All rights reserved.