Pinch-to-zoom on embedded Google Map zooms whole page - javascript

How can I get pinch-to-zoom to work properly in my Google Maps v3-based web app? Right now, pinching on a touchscreen Windows 8 device will zoom the whole page, not the map. I've tried this in both Chrome and Firefox, and it works properly on the Google Maps site, but not on my site.
I have the following meta tag in my <head> element, but it doesn't seem to help. Is there another meta tag I need to add? I checked out the source of the Google Maps site but couldn't find any meta tags that looked relevant.
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">

this is most likely because you're using an overlay.
you can block pinch and drag by adding this code:
window.blockMenuHeaderScroll = false;
$(window).on('touchstart', function(e)
{
if ($(e.target).closest('#map').length == 1)
{
blockMenuHeaderScroll = true;
}
});
$(window).on('touchend', function()
{
blockMenuHeaderScroll = false;
});
$(window).on('touchmove', function(e)
{
if (blockMenuHeaderScroll)
{
e.preventDefault();
}
});
thanks to https://stackoverflow.com/a/17159809

If you don't specify explicit gestureHandling for the 2D Map then it can happen that the map element defaults to "greedy" behavior. This can surely happen if your map is not inside an iframe. With greedy behavior the map will hijack more gestures than in "cooperative" mode. See Controlling Gesture Handling.
When the gesture handling is greedy than you won't see the "Use two fingers to move the map" message over the 2D Map when you scroll over it with flick gestures. In such cases explicitly specifying cooperative gesture handling helps, although it may not fix the problem fully, because the issue is also browser dependent. Even with cooperative I may see a little page zoom on Android Chrome based browser, but the behavior is much better.
new google.maps.Map(document.getElementById("map"), {
zoom,
center,
gestureHandling: "cooperative",
});
As for #jimmy's answer below I'd highly disadvise handler manipulation JavaScript hackery, the good news is that there's native support on the v3 Maps API to disable pan and zoom or even restrict bounds.

Related

How to replicate the pinch zoom interaction of google maps and leaflet.js (trackpad and mobile)

I am curious how to recreate the way pinch zoom works on map tools like google maps and leaflet.js
On any other site, when you pinch zoom the entire browser windows gets magnified on whatever you are pinch zooming on.
On Google Maps or Leaflet.js, when you pinch zoom on the map it seems to override that functionality and makes the map zoom in and out in the exact same way as it would if you were scrolling with your fingers or a mouse wheel.
How might they go about doing that?
To clarify - I don't want to disable zoom in the viewport either. I just want a specific section of a page to ignore the standard pinch zoom (with track pad or mobile) and instead interpret the pinch zoom as a standard scroll wheel event only
This seems to be working - but if anyone has a better suggestion let me know.
element.addEventListener('wheel', event => {
const { ctrlKey } = event
if (ctrlKey) {
event.preventDefault();
return
}
}, { passive: false })
I specify the div and now pinch zoom works everywhere else but that element

user-scalable=no but still able to scale entire page on web map application?

I have a web application that is essentially a map (mapbox) with some d3.js points overlayed, filters, etc.
My issue is that when zooming in on the map using pinch (mobile), when I accidentally pinch over one of the points, or one of the map pop-ups, the entire page zooms (i.e. scaling). This is a fairly common occurrence. I only want user to be able to zoom the map, not the page itself.
I've implemented:
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
I also tried user-scalable=0
And still the behavior persists. I've also tried this:
document.addEventListener("touchstart", function(e){
e.preventDefault();
},{passive: false});
document.getElementById('map')
.addEventListener('touchstart', function(e){e.stopPropagation()}, false);
But this is cumbersome and doesn't exactly work the greatest because it involved limiting event-listeners one element at a time. Shouldn't the user-scalable argument in the HTML be enough? I don't understand why this is happening.
Mobile browsers have no effect on user scalable because they over ride it to get people responsive experience on the mobiles.
Sites like google maps also zoom when we pinch in the site(expanding the ui elements as well as the map)
One way to override this response is to detect the pinch gesture and then re zoom the page to the normal level by a function such as:
function toggleZoomScreen() {document.body.style.zoom = "100%”;}
Shouldn't the user-scalable argument in the HTML be enough?
Depends on the browser/device. There are not many legitimately cases where zooming should be disallowed, so browsers will ignore it. Some browsers like Safari uses heuristics based on text size to decide if it should zoom or not... (where the solution is to set font-size to 17px or higher on input elements to prevent zoom)
First strategy would be to call preventDefault() on all mouse
events, like mouseup, mousedown, et.al (not just the touch events)
until you are able to block the zoom.
Second strategy is to take into account the zoom and scale the
images and point locations by the amount of zoom...
(Probably also want to take into account window.devicePixelRatio when scaling.)

Getting relative touch coordinates inside canvas

I've been working on my first HMLT5 game prototype for the past few days, and I need to make it work on both desktop and mobile. The problem is, I'm new on web development in general.
To get the mouse/touch position relative to the canvas I've stoped using e.layerX or e.offsetX and started using this method. I even added <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">.
But even after that, touch coordinates come offset when rotating the screen, and Dolphin also treats touch in a very weird way.
Is there any general way to deal with this? I'm not familiar with the technologies so maybe use jQuery or something similar?
Edit: Also, pageX screenX and clientX all return the same value. No idea why, I used e.touches[0].clientX.
Edit2: I think I solved it. Forgot I had to call findPos(obj); again if the screen rotated. I don't even want to test it without the meta tag, I'll leave it like that for now.
I use this (via JQuery) to get my mouse position in a Canvas, relative to the canvas:
canvas.mousemove(function(e){
mmouseX = e.pageX-canvas.position().left;
mmouseY = e.pageY-canvas.position().top;
}
Tried it on Android default browser and it works ok, as well as on Desktops. Never tried it with Dolphin though.

How to resolve map zoom and page zoom conflict on mobile website?

I have a website that displays a mashup on Google Map. When I try to zoom into the map on a mobile web browser, the page gets the zoom instead on most occasions. Is there a HTML, CSS or javascript method that prevents the page from zooming while my fingers are touching the map?
I tried <meta name='viewport' content='user-scalable=no'>, but that prevents the map from zooming as well.
This can be done by using Gesture events.You can call touchstart event, and then call
e.originalEvent.preventDefault(); //if you are using JQuery
this prevent your page from zoom in.

Javascript web-app, control iPhone zooming on input focus and blur

I created a web-app a couple years ago (JS/CSS/HTML over a LAMP backend) which has been working fine. The client is now using it on his iPhone, and reports that when on a login screen with 2 inputs, the window zooms in 'too much' and when he's done entering input, it doesn't zoom back to the 'normal' zoom level (from screengrabs he sent, it looks like it zooms back to somewhere between 'normal' and the zoom level used when typing into the input).
Is it possible to control either behavior? I've read about the meta of user-scalable:0 but that sounds like it'd either A) not work at all or B) prevent zooming altogether.
I'd say the second issue is more critical (after the user inputs text, it should zoom back to 'normal' scale).
i'll mention again this is a generic web-app and not an 'iPhone app' (it's built on traditional web technologies, not Cocoa or Objective-C). I don't even own an iPhone, or a Mac that I can use an emulator on, and the windows emulators I've seen seem to be nothing more than iframes in a graphic.
thanks
If you leave user zooming option, it is up to him to go back to website original zoom scale. Iphone safary browser in portrait mode makes a zoom-in, everytime keyboard or combobox is opened. Then it does not zoom back to original scale (it has to be done by double tapping the screen or pinching the screen...).
Other option is not letting the user zooming with viewport meta tag
<meta name="viewport" id="view" content="user-scalable=no, width=device-width, initial-scale=1.0" />
Then iphone wont zoom when keyboard is opened or when spinner is opened
Im currently looking for a way of solving it (merge zooming possibility with avoiding zoom when keyboard opens), but I did not find any way to do it...
I solved it playing with viewport: As you said, when there is not user zoom enabled then openning keyboard or combo does not make zoom, but then you loose zooming feature for users.
I disable zoom on viewport when a combo is selected and then I restore zoom option after one second:
document.documentElement.addEventListener("touchstart", function (event) {
if((event.target.nodeName == "SELECT") || (event.target.nodeName == "INPUT") || (event.target.nodeName == "TEXTAREA")) { //it is a combo
document.getElementById("view").setAttribute('content', 'width=device-width, user-scalable=no');
setTimeout(function () {
document.getElementById("view").setAttribute('content', 'width=device-width, user-scalable=yes');
}, 1000);
}
}, true);
Not to say that my viewport has "view" as id.
Yes, I know it is not best solution, but it works...

Categories