Leaflet Touch Events not firing - javascript

// Setup map
var polymap = L.map('map').setView([51.932994, 4.509373], 14);
// Setup tilelayer
var mapquestUrl = 'http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png',
subDomains = ['otile1', 'otile2', 'otile3', 'otile4'],
mapquestAttrib = 'Data, imagery and map information provided by MapQuest,'
+ 'OpenStreetMap and contributors.';
var osm = L.tileLayer(mapquestUrl, {
attribution: mapquestAttrib,
subdomains: subDomains
});
polymap.addLayer(osm);
polymap.on('mousedown touchstart', function onMouseDown(event) {
alert("start");
});
JSFiddle
Leaflet should normally fire the touchstart event as it does with the mousedown event, but using a mobile phone, I get no event fired.
Can somebody tell me if there's any mistake in the code, that prevents the touchevent from firing?

I have added touch events to leaflet in a branch https://github.com/lee101/Leaflet/tree/add-mobile-touch-events
There is still a problem with touchend events not getting fired if a touchstart event happens on a map control.
You can build the source with npm install && jake after you clone the repository.
I should hopefully contribute it back after i fix that issue.

It is difficult to get normal touch events working properly with leaflet map because the map itself use touch events to permit zoom & pan function.
To avoid this issue, you may use this
library to catch specific touch event (tap,double tap,press,flick,drag)
<script src="http://domain.ltd/path/jquery.finger.js"></script>
$.Finger = {
pressDuration: 300,
doubleTapInterval: 300,
flickDuration: 150,
motionThreshold: 5
};
polymap.on('tap', function(e) {
alert("start");
});
Best regards

Related

How to get click location from custom event handler Leaflet

I'm trying to write a custom event handler for CTRL + click in Leaflet. My problem is that the click location given by the map is different from the click location in the event handler, e.g. LatLng(51.49174, -0.11639) from the map click becomes LatLng(51.50938, -0.126) in the handler. The click locations match exactly if the map is the only thing on the page. Adding some other div elements above the map (like an <h1> title) makes the clicks not match. Panning the map also makes the click locations not match.
I'm wondering if I attached my L.DomEvent.on() correctly. Following the Leaflet Handlers tutorial, my code looks like
L.CtrlClickHandler = L.Handler.extend({
addHooks: function() {
L.DomEvent.on(document, 'click', this._captureClick, this);
},
removeHooks: function() {
L.DomEvent.off(document, 'click', this._captureClick, this);
},
_captureClick: function(event) {
if (event.ctrlKey) {
console.log('control click registered at layer '
+ map.layerPointToLatLng(new L.point(event.layerX, event.layerY)));
}
}
});
// add this to all maps
L.Map.addInitHook('addHandler', 'ctrlClick', L.CtrlClickHandler);
Here's a live example on JSFiddle.
I'm using Leaflet 0.7.7 due to some other dependencies in my code. Upgrading to Leaflet 1.0.1 makes it match better (e.g., LatLng(51.49868, -0.1018) vs. LatLng(51.4987, -0.1018)) but the two locations still are not exactly the same.
Am I attaching the L.DomEvent to the correct thing? Should that be attached to the map div somehow, as opposed to document?
Edit: Thanks to #AlexParij for the suggestion. I realized that panning the map also makes the clicks not match, with or without div elements above the map. This happens for Leaflet 1.0.1 as well as 0.7.7. I've tried every combination I can think of, combining different event locations (event.layerX, event.pageX, event.clientX, event.offsetX, event.screenX, and event.x) with projection methods layerPointToLatLng and unproject but none of them match the map click. Now I'm really confused... Fiddle with these different options and Leaflet 1.0.1: https://jsfiddle.net/c4tkyewz/
TL; DR: use map.mouseEventToLatLng() in a custom handler.
#AlexParij was correct; I was not using the correct definition of the layer points and container points. Inside the handler, event is different from Leaflet's internal mouse event (where the location is available from e.latlng).
I looked through Leaflet's core to find the answer. Getting the location from event requires taking the Mouse Event -> Container Point -> Layer Point -> latLng. Thankfully, the Leaflet developers already programmed a nice function for this: mouseEventToLatLng().
/*
* This is a custom handler to check if someone has control clicked
* the map and print the location of the click
*/
L.CtrlClickHandler = L.Handler.extend({
addHooks: function() {
L.DomEvent.on(document, 'click', this._captureClick, this);
},
removeHooks: function() {
L.DomEvent.off(document, 'click', this._captureClick, this);
},
_captureClick: function(event) {
if (event.ctrlKey) {
// translate mouse event to lat/lng (note: `mouseEventToLatLng()`
// calls Leaflet's `mouseEventToContainerPoint()` followed by
// `containerPointToLayerPoint()` and finally `layerPointToLatLng()`)
var latlng = map.mouseEventToLatLng(event);
console.log('Handler detected CTRL + click at ' + latlng);
}
}
});
// add this to all maps
L.Map.addInitHook('addHandler', 'ctrlClick', L.CtrlClickHandler);
Live example with Leaflet 1.0.1: https://jsfiddle.net/c4tkyewz/1/
Also tested with Leaflet 0.7.7.
As a bonus, to access the CTRL key directly from Leaflet's native handling of the click event map.on('click', function(e) {});, use e.originalEvent.ctrlKey.

Open Layers 3 Zoom map event handler

I need to handle a zoom event in Open Layers 3.
The following is my code:
map_object = new ol.Map({
target: 'map',
controls: controls_list,
interactions: interactions_list,
overlays: [overlay],
layers: [OSM_raster, WFS_layer],
view: view
});
map_object.on("Zoom", function() {
console.log('Zooming...');
});
This code runs with no errors and shows a map, but there is no output to the console, suggesting this function isn't firing.
I have also tried:
map_object.on("drag", function() {
console.log('Dragging...');
});
And this too does nothing.
Any help as to how to handle map control events in OL3 would be much appreciated (particularly zooming!). Note I have tried 'zoom' as well as 'Zoom' for the type field of the on method.
Just to add to this, you can check variations of events available with 'propertychange', from what I am seeing, there is no explicit .on ('zoom', ...) but rather you can access 'resolution' and other properties as mentioned in previous comments:
map.getView().on('propertychange', function(e) {
switch (e.key) {
case 'resolution':
console.log(e.oldValue);
break;
}
});
try with moveend event. (see https://openlayers.org/en/latest/apidoc/module-ol_MapEvent-MapEvent.html#event:moveend).
As mentioned by tonio, the way to listen on zoom change, which is called resolution change in openlayers terminology, is with
map.getView().on('change:resolution', (event) => {
console.log(event);
});
I find this is better (more succinct, less cruft) than listening on the general propertychange and verifying manually if the change concerns resolution.
This fires rapidly when using the mouse button so throttling it might be a good idea before launching any computation that waits for it to change.
Documentation for View
You can manage the moveend event...
We will need a global variable to alocate map’s view zoom level. I’ve
named it as currentZoomLevel.
There is available a moveend event. Let’s use it, and add a zoom level
check function..
In case of there’s a new zoom level, we trigger a zoomend event to
DOM’s document.
Finally we will need to add zoomend listener to the document element.
var = currentZoomLevel;
map.on('moveend', checknewzoom);
function checknewzoom(evt)
{
var newZoomLevel = map.getView().getZoom();
if (newZoomLevel != currentZoomLevel)
{
currentZoomLevel = newZoomLevel;
$(document).trigger("zoomend", zoomend_event);
}
}
$(document).on('zoomend', function () {
console.log("Zoom");
//Your code here
});
Source

Hammer js dragging

I have the following code which I got from the hammer documentation, however the listener isn't firing for me. I can't figure out why I can't get drag to work.
Also, I attempted to do my own drag like feature using tap, pan, but again how do I get an event for detecting a release? I see examples online with people using: touch.on("release", function(ev) {}); but I get absolutely nothing.
var options = {
dragLockToAxis: true,
dragBlockHorizontal: true
};
//Hammer.js dependency. Setup touch
touch = new Hammer(el, options);
touch.on("dragleft dragright", function(ev) {
console.log("handle released");
});
It's pan not drag (not sure when they changed it)
http://jsbin.com/suleyilejili/2/edit
http://hammerjs.github.io/recognizer-pan/

How can I differentiate between a click and a drag in Google Maps JS API v3 on Mobile?

I'm building a mobile-capable HTML5 site with Bootstrap, jQuery and the Google Maps v3 API.
I've figured out most of the code, I want to be able to click, add a marker, HTTP POST that location to the server (for storing it).
I initially had trouble getting android to see that a click should happen on touch.
if ($.browser.mobile) {
google.maps.event.addListener(map, 'mousedown', function(event) {
placeMarker(event.latLng);
});
} else {
google.maps.event.addListener(map, 'click', function(event) {
placeMarker(event.latLng);
});
}
}
I'm using http://detectmobilebrowsers.com/ jQuery code to do the $.browser.mobile thing.
The problem I'm having is that if I click the map, to drag it, and move to a different location on mobile, it calls placeMarker(), which is understandable, if irritating, so the process of dragging the map creates markers (and POSTs to the server).
Is there any way I can detect, if a drag has taken place, so I can tell it to not bother doing placeMarker and POST?
See if code like this will work for you:
google.maps.event.addListener(map, 'mousedown', function(event) {
var initPoint = {x: event.pageX, y: event.pageY},
toBeCanceled = false,
latLong = event.latLong;
google.maps.event.addListener(map, 'mousemove', function(event) {
var newPoint = {x: event.pageX, y: event.pageY};
// if newPoint has moved beyond expected limits
toBeCanceled = true
});
google.maps.event.addListener(map, 'mouseup', function(event) {
if (toBeCanceled) {
event.preventDefault() // event.stop() seems to work as commented by OP
} else {
placeMarker(event.latLng);
}
// Unregister mousemove and mouseup
});
});
Instead of mousedown event, I would rather use dragstart, dragend, drag events.
You could also replace click with dblclick, if that does not impact the user experience you want to present to your users. I do not know how "click" interacts with the "drag" event.

map.on('click',onClick) is also fired when zoomBox

I have defined a map.on('click',onClick) event, but it also fires when someone uses the zoomBox Handler (Shift+draw zoom box)
function onClick(e) {alert(e.latlng);}
e.type is always 'click'
I am using Leaflet version 0.5.1.
How can I avoid this?
thanks in advance
I think you found a bug! I found this bug appears in IE 10 only, and not only 0.5.1, but 0.6 also has same issue. You can report a bug to Leaflet issue tracker.
For now, temporary, you can track mousedown point and compare to click point to determine whether cursor is moved.
var mousedownPoint; // global
map.on('mousedown', function (e) {
mousedownPoint = e.containerPoint;
});
map.on('click', function (e) {
if (!e.containerPoint.equals(mousedownPoint)) {
return;
}
// DO WHAT YOU WANT
});

Categories

Resources