JavaScript touch events contain properties for radius and force. Unfortunately it appears that events aren't generated when either property changes. Events are only triggered for things like touch start, move or end. Can anyone think of a way to get more updates on change of touch size?
Currently to get radius updates I have to wiggle my finger to trigger the touch move event, but I would prefer a software solution.
I had the same issue and then discovered this blog post: http://blog.framerjs.com/posts/prototyping-3D-touch-interactions.html
In a nutshell, we need to use touchstart event to capture the touch event, assign the event to a variable and then use setInterval to get the force value:
var el = document.getElementById('myElement');
var currTouch = null;
var currTouchInterval = null;
attachListeners = function () {
el.addEventListener('touchstart', enterForceTouch, false);
el.addEventListener('touchend', exitForceTouch, false);
}
enterForceTouch = function (evt) {
evt.preventDefault();
currTouch = evt;
currTouchInterval = setInterval(updateForceTouch, 10); // 100 times per second.
}
updateForceTouch = function() {
if (currTouch) {
console.log(currTouch.touches[0].force); // Log our current force value.
}
}
exitForceTouch = function (evt) {
evt.preventDefault();
currTouch = null;
clearInterval(currTouchInterval);
}
attachListeners();
I am using google 'idle' event listener to upload markers on map (with angularjs). My code is
$scope.LoadSearchPropertyOnPortFolioSales = function (PropertyName) {
if(PropertyName == ''){
google.maps.event.addListener(map, 'idle', function () {
var PropertyList = PropertyService.GetSearchPropertyForPortfolio($scope.PortfolioId, $scope.PropertyName, this.center.lat(), this.center.lng(), 0.005, 0.005);
PropertyList.then(function (pl) {
DrawPropertyOnPortFolioSale(pl.data, $scope.PropertyName);
},
});
}
else
{
//Stop event listener
}
}
I want the event listener only work when PropertyName that is passed have no value. But when PropertyName have some value in it i want to stop event listener. How do i stop event listener......
There's also a function which removes all of the listeners at the same time:
clearListeners(instance:Object, eventName:string);
//In your case:
google.maps.event.clearListeners(map, 'idle');
Here's the Google Maps API reference where you can read about it.
I currently have this bit of code, functioning like I want. I blank out the JSON that is loaded w/ the mapbox map, load one a JSON set from a local file and filter some points out. Was able to figure this out thanks to a previous post.
Now, I'm wanting to auto-pan/zoom the map to encompass only the markers that are visible and having no luck. I've tried several variations of fitBounds and map.extent and feeding it with map.markerLayer.getGeoJSON or markerLayer.getGeoJSON. The former throws a console error of "lat" undefined, which sent me on a console.log hunt and it seems that when you use loadURL, getGeoJSON no longer returns any results?
Thanks for the help. Here's the code.
var statestring = String(Request.QueryString("location"));
var map = L.mapbox.map('map', 'aam.map-ryzdcons');
map.markerLayer.setGeoJSON([]);
var markerLayer = L.mapbox.markerLayer()
.loadURL('markers.geojson.txt')
.setFilter(function(f) {
return f.properties['coverage'].toLowerCase().indexOf(statestring.toLowerCase()) > -1 ; })
.addTo(map);
Between here I tried to put map.fitBounds(markerLayer.getBounds()); w/ no success and some other variations.
markerLayer.on('mouseover', function(e) {
e.layer.openPopup();
});
markerLayer.on('mouseout', function(e) {
e.layer.closePopup();
});
Edit #2: I just tried this, proving my theory that getGeoJSON indeed DOES NOT work when setting loadURL first. It sort of works but doens't accomplish what I want obviously.
$.getJSON("markers.geojson.txt", function (data) {
map.markerLayer.setGeoJSON(data);
map.fitBounds(markerLayer.getBounds());
if (markers.length == '1') {
map.setZoom(8);
}
map.markerLayer.setGeoJSON([]);
});
Edit #3 because it won't let me answer my question for another couple hours:
The answer is: you have to wait for the ready event, at least in my case. Moved the stuff in edit #2 to a markerLayer.on ready event.
var markers = [];
markerLayer.on('ready', function(e) {
this.eachLayer(function(marker) { markers.push(marker); });
map.fitBounds(markerLayer.getBounds());
if (markers.length == '1') {
map.setZoom(8);
}
//alert(markers.length);
});
The answer is: you have to wait for the ready event, at least in my case. Moved the stuff in edit #2 to a markerLayer.on ready event.
var markers = [];
markerLayer.on('ready', function(e) {
this.eachLayer(function(marker) { markers.push(marker); });map.fitBounds(markerLayer.getBounds());
if (markers.length == '1') {
map.setZoom(8);
}
//alert(markers.length);
});
Is there any event to check if user end zoomed in a map or end zoomed out the map
What we do is.. we want to send the latitude or longtitude to server when they making change to the map. for example when they end dragging we will send the latitude and longtitude to server to load some shop location that are within boundary of that latitude and longtitude and we will put the pins on it. so all the possible event are user dragging map, zoom in, zoom out and scrolling. we will not use bounds_changed event because it will send data to the server all the time.
//Get bound of the map when a user dragged the map.
google.maps.event.addListener(map, 'dragend', function () {
bound = map.getBounds();
var latlng_NE = bound.getNorthEast();
var latlng_SW = bound.getSouthWest();
// Some code to send latitude or longtitude to server here
throw new Error(latlng_NE, latlng_SW);
});
From the Google Maps API doc
google.maps.event.addListener(map, 'zoom_changed', function() {
setTimeout(moveToDarwin, 3000);
});
https://developers.google.com/maps/documentation/javascript/events;
edit
// closure
(function() {
var timeout = null;
var delay = 500;
function react() {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(react, delay)
}
function sendBoundsToServer() {
bound = map.getBounds();
var latlng_NE = bound.getNorthEast();
var latlng_SW = bound.getSouthWest();
// some AJAX action to send bound to server
// ...
}
//Action after a user dragged the map.
google.maps.event.addListener(map, 'zoom_changed', function () {
// Some code to send latitude or longtitude to server here
setTimeout(sendMessageToServer, 1000)
});
google.maps.event.addListener(map, 'dragend', function () {
// Some code to send latitude or longtitude to server here
setTimeout(react, 1000)
});
// Add more events here like the two above
}())
With the Google Maps JS API v3, I want to drop a marker where the user clicks on the map, while keeping the default behavior when the user double clicks (and not adding any marker on the map).
I thought about defining a timeout on click event. If a double click event is triggered within the next few milliseconds, the timeout is cancelled. If not, the marker is placed on the map when the timeout expires.
But it doesn't really look like the best solution ever.
Is there a more elegant way to handle this?
Thanks.
I just found an hackish solution which works but introduce a small waiting time (200ms, this is the minimum to make it work, but I don't know if it is client dependent)
var update_timeout = null;
google.maps.event.addListener(map, 'click', function(event){
update_timeout = setTimeout(function(){
do_something_here();
}, 200);
});
google.maps.event.addListener(map, 'dblclick', function(event) {
clearTimeout(update_timeout);
});
Hope this helps!
The easiest way to solve it.
var location;
var map = ...
google.maps.event.addListener(map, 'click', function(event) {
mapZoom = map.getZoom();
startLocation = event.latLng;
setTimeout(placeMarker, 600);
});
function placeMarker() {
if(mapZoom == map.getZoom()){
new google.maps.Marker({position: location, map: map});
}
}
shogunpanda's solution is better (see below)
You can take advantage of, dblclick fires if it is a double click, and single click fires in such occations only once.
runIfNotDblClick = function(fun){
if(singleClick){
whateverurfunctionis();
}
};
clearSingleClick = function(fun){
singleClick = false;
};
singleClick = false;
google.maps.event.addListener(map, 'click', function(event) {// duh! :-( google map zoom on double click!
singleClick = true;
setTimeout("runIfNotDblClick()", 500);
});
google.maps.event.addListener(map, 'dblclick', function(event) {// duh! :-( google map zoom on double click!
clearSingleClick();
});
See http://www.ilikeplaces.com
If you're using underscore.js or* lodash here's a quick and elegant way to solve this problem
// callback is wrapped into a debounce function that is called after
// 400 ms are passed, it provides a cancel function that can be used
// to stop it before it's actually executed
var clickHandler = _.debounce(function(evt) {
// code called on single click only, delayed by 400ms
// adjust delay as needed.
console.debug('Map clicked with', evt);
}, 400);
// configure event listeners for map
google.maps.event.addListener(map, 'click', clickHandler);
google.maps.event.addListener(map, 'dblclick', clickHandler.cancel);
* Debounce.cancel is implemented only in lodash (with this commit), underscore.js does not implement it
A cleaner way to implement the setTimeout() approach is to trigger custom events for single clicks.
The following function takes any Google Maps interface object (e.g. map, marker, polygon etc.) and sets up two custom events:
singleclick: called 400ms after a click if no other clicks have occured
firstclick: called whenever a click event occurs, unless a click has already occured in the last 400ms (this is handy for showing some kind of immediate click feedback to the user)
function addSingleClickEvents(target) {
var delay = 400;
var clickTimer;
var lastClickTime = 0;
google.maps.event.addListener(target, 'click', handleClick);
google.maps.event.addListener(target, 'dblclick', handleDoubleClick);
function handleClick(e) {
var clickTime = +new Date();
var timeSinceLastClick = clickTime - lastClickTime;
if(timeSinceLastClick > delay) {
google.maps.event.trigger(target, 'firstclick', e);
clickTimer = setTimeout(function() {
google.maps.event.trigger(target, 'singleclick', e);
}, delay);
} else {
clearTimeout(clickTimer);
}
lastClickTime = clickTime;
}
function handleDoubleClick(e) {
clearTimeout(clickTimer);
lastClickTime = +new Date();
}
}
You can use it like so:
var map = ....
addSingleClickEvents(map);
google.maps.event.addListener(map, 'singleclick', function(event) {
console.log("Single click detected at: " + event.latLng);
}
I'm not sure, but if you add event handlers to both 'click' & 'dblclick' events, where you say to put marker on a click, and don't take any action on double click, then you can skip the adding of timeouts (the maps API can differ what is click and what is double click)
google.maps.event.addListener(map, 'click', function (event) {
placeMarker(event.latLng);
});
google.maps.event.addListener(map, 'dblclick', function(event) {
//DO NOTHING, BECAUSE IT IS DOUBLE CLICK
});
The placeMarker(latLng) is custom added function which adds marker on the given location:
var marker = new google.maps.Marker({
position: location,
draggable: true,
map: map
});
map.setCenter(location);