I'm currently building a Phonegap app along with Google's Map JS API.
我目前正在构建一个Phonegap应用程序以及Google的Map JS API。
I have a map that you can drag to select your dropoff location. This is accomplished by collecting the map's center geolocation on the "dragend" event. I then set a pin on top of the map (outside of the JS map) so that you know where the center point is.
我有一张地图,您可以拖动以选择您的下车位置。这是通过在“dragend”事件中收集地图的中心地理位置来实现的。然后我在地图顶部(JS地图之外)设置一个引脚,以便您知道中心点的位置。
Everything works fine until you pinch to zoom and the pin is then displaced. This is due to you zooming and dragging the map at the same time when pinching the screen.
一切正常,直到你捏缩放,然后销钉移位。这是因为您在挤压屏幕的同时缩放和拖动地图。
Is there any way to prevent dragging on zoom in order to hold the map at its center point?
有没有办法阻止拖动缩放,以便将地图保持在其中心点?
Please view the JSfiddle here.
请在这里查看JSfiddle。
var map;
google.maps.event.addDomListener(window, 'load', onMapReady);
function onMapReady() {
var center = new google.maps.LatLng(30.267153, -97.743061);
var mapOptions = {
center: center,
zoom: 13,
styles: [{"featureType": "poi", "stylers": [{ "visibility": "off" }]},{"featureType": "transit","stylers": [{ "visibility": "off" }]}],
disableDefaultUI: true,
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
google.maps.event.addListener(map, 'dragend', function() {
center = map.getCenter();
$('#log').html('Lat: ' + center.lat() + ' Lng: ' + center.lng());
});
}
3 个解决方案
#1
2
There are two possible solutions for this issue , from what i have read that you have tried using native marker but it is lagging , which itself is another issue that i have a suggestion for :
对于这个问题,有两种可能的解决方案,从我读过的你已经尝试过使用原生标记但它是滞后的,这本身就是另一个问题,我有一个建议:
-
use crosswalk for building your app , this will extremely boost your app performance , i have experienced it myself , and was really satisified with results ( iam using intel xdk but i believe this will work for phonegap as well ).
使用crosswalk构建你的应用程序,这将极大地提升你的应用程序性能,我自己经历过,并且对结果非常满意(我使用intel xdk,但我相信这也适用于phonegap)。
-
use the UX solution : you feel the marker is lagging because after all it is visible !! i would suggest hiding the marker on drag event start , then showin it back on drag event end.
使用UX解决方案:你觉得标记是滞后的,因为它毕竟是可见的!!我建议在拖动事件开始时隐藏标记,然后在拖动事件结束时显示它。
-
Third solution which makes sense , is using a pinch detector library like this , this , or even solutions mentioned here , and here , pick whatever works best for you , as performance is a point of concern , and previous solution have to be tried , however once you have detected the pinch gesture , you set the map drag to false , set it back again to true after pinch ends .
有意义的第三个解决方案是使用像这样的夹点检测器库,这个,甚至是这里提到的解决方案,在这里,选择最适合你的方法,因为性能是一个值得关注的问题,并且必须尝试以前的解决方案,一旦检测到捏合手势,就将地图拖动设置为false,在捏合结束后再将其设置为true。
I dont usually provide much coding in my solution but rather the correct algorithm to help solving the specified issue.
我通常不会在我的解决方案中提供太多编码,而是帮助解决指定问题的正确算法。
#2
1
EDIT: ProllyGeek is right, the zoom_changed event fires after the drag has already happened. You can detect if the touch event was near the center of the map (over your marker) and re-center the map after zooming:
编辑:ProllyGeek是正确的,在拖动已经发生后,zoom_changed事件将触发。您可以检测触摸事件是否在地图中心附近(在标记上方)并在缩放后重新居中地图:
google.maps.event.addListener(map, 'dragend', function() {
if (center && center != map.getCenter()) {
map.setCenter(center);
center = null;
}
});
//we should recenter the map if the click/mousedown was within the centerRadius of the center of the map
google.maps.event.addListener(map, 'mousedown', function(clickMouseEvent) {
var mapDiv = document.getElementById('map');
if (pointInCircle(clickMouseEvent.pixel.x,
clickMouseEvent.pixel.y,
mapDiv.offsetWidth/2,
mapDiv.offsetHeight/2,
centerRadius)) {
//map.setOptions({draggable: false}); //disables zoom and dragging
center = map.getCenter(); //save the current center point so we can recenter later.
}
});
//handy function to see if a x,y coordinate is within z radius of another x,y coordinate
//from https://*.com/a/16819053/1861459
function pointInCircle(x, y, cx, cy, radius) {
var distancesquared = (x - cx) * (x - cx) + (y - cy) * (y - cy);
return distancesquared <= radius * radius;
}
http://jsfiddle.net/bxfn499f/11/
http://jsfiddle.net/bxfn499f/11/
Original Answer:
原答案:
Did you try setting draggable to false on the map when the zoom event is fired?
在触发缩放事件时,您是否尝试在地图上将draggable设置为false?
google.maps.event.addListener(map, 'zoom_changed', function() {
map.setOptions({draggable: false});
//heavy handed re-enabling of draggable
//setTimeout(function() { map.setOptions({draggable: true}); }, 5000); //cant drag for five seconds
});
You can programmatically re-enable dragging with the mouseup event (which should fire in lieu of the touchend
event) or whatever makes sense in your use case (map.setOptions({draggable: true});
). For example:
您可以使用mouseup事件(应该触发代替touchend事件)或者在用例中有意义的任何内容(map.setOptions({draggable:true});)以编程方式重新启用拖动。例如:
google.maps.event.addListener(map, 'mouseup', function() {
map.setOptions({draggable: true});
});
http://jsfiddle.net/bxfn499f/6/ I tested from a desktop, so I tweaked the fiddle slightly as the map wasn't loading for me - assuming this was due to the window.load not being fired after $(document).ready(function() { ... }
. You'll have to see how this behaves if the drag stars before the zoom event.
http://jsfiddle.net/bxfn499f/6/我在桌面上进行了测试,所以我稍微调整了小提琴,因为地图没有为我加载 - 假设这是由于window.load在$(文件后)没有被触发).ready(function(){...}。如果拖动在zoom事件之前出现,你将不得不看看它是如何表现的。
#3
1
I have a solution which might work. Assuming you want the map to center back to the pin.
我有一个可行的解决方案。假设您希望地图中心回到引脚。
Add custom control div in your map object. The example is here. Instead of the "center map" div in the example, make your pin the controlling div. Listen to dragend
event and set the center at pin's position.
在地图对象中添加自定义控件div。这个例子在这里。而不是示例中的“中心地图”div,使您的引脚成为控制div。收听dragend事件并将中心设置在引脚位置。
Haven't really tested the solution but seems like it will do the trick.
还没有真正测试过这个解决方案,但似乎它会做到这一点。
#1
2
There are two possible solutions for this issue , from what i have read that you have tried using native marker but it is lagging , which itself is another issue that i have a suggestion for :
对于这个问题,有两种可能的解决方案,从我读过的你已经尝试过使用原生标记但它是滞后的,这本身就是另一个问题,我有一个建议:
-
use crosswalk for building your app , this will extremely boost your app performance , i have experienced it myself , and was really satisified with results ( iam using intel xdk but i believe this will work for phonegap as well ).
使用crosswalk构建你的应用程序,这将极大地提升你的应用程序性能,我自己经历过,并且对结果非常满意(我使用intel xdk,但我相信这也适用于phonegap)。
-
use the UX solution : you feel the marker is lagging because after all it is visible !! i would suggest hiding the marker on drag event start , then showin it back on drag event end.
使用UX解决方案:你觉得标记是滞后的,因为它毕竟是可见的!!我建议在拖动事件开始时隐藏标记,然后在拖动事件结束时显示它。
-
Third solution which makes sense , is using a pinch detector library like this , this , or even solutions mentioned here , and here , pick whatever works best for you , as performance is a point of concern , and previous solution have to be tried , however once you have detected the pinch gesture , you set the map drag to false , set it back again to true after pinch ends .
有意义的第三个解决方案是使用像这样的夹点检测器库,这个,甚至是这里提到的解决方案,在这里,选择最适合你的方法,因为性能是一个值得关注的问题,并且必须尝试以前的解决方案,一旦检测到捏合手势,就将地图拖动设置为false,在捏合结束后再将其设置为true。
I dont usually provide much coding in my solution but rather the correct algorithm to help solving the specified issue.
我通常不会在我的解决方案中提供太多编码,而是帮助解决指定问题的正确算法。
#2
1
EDIT: ProllyGeek is right, the zoom_changed event fires after the drag has already happened. You can detect if the touch event was near the center of the map (over your marker) and re-center the map after zooming:
编辑:ProllyGeek是正确的,在拖动已经发生后,zoom_changed事件将触发。您可以检测触摸事件是否在地图中心附近(在标记上方)并在缩放后重新居中地图:
google.maps.event.addListener(map, 'dragend', function() {
if (center && center != map.getCenter()) {
map.setCenter(center);
center = null;
}
});
//we should recenter the map if the click/mousedown was within the centerRadius of the center of the map
google.maps.event.addListener(map, 'mousedown', function(clickMouseEvent) {
var mapDiv = document.getElementById('map');
if (pointInCircle(clickMouseEvent.pixel.x,
clickMouseEvent.pixel.y,
mapDiv.offsetWidth/2,
mapDiv.offsetHeight/2,
centerRadius)) {
//map.setOptions({draggable: false}); //disables zoom and dragging
center = map.getCenter(); //save the current center point so we can recenter later.
}
});
//handy function to see if a x,y coordinate is within z radius of another x,y coordinate
//from https://*.com/a/16819053/1861459
function pointInCircle(x, y, cx, cy, radius) {
var distancesquared = (x - cx) * (x - cx) + (y - cy) * (y - cy);
return distancesquared <= radius * radius;
}
http://jsfiddle.net/bxfn499f/11/
http://jsfiddle.net/bxfn499f/11/
Original Answer:
原答案:
Did you try setting draggable to false on the map when the zoom event is fired?
在触发缩放事件时,您是否尝试在地图上将draggable设置为false?
google.maps.event.addListener(map, 'zoom_changed', function() {
map.setOptions({draggable: false});
//heavy handed re-enabling of draggable
//setTimeout(function() { map.setOptions({draggable: true}); }, 5000); //cant drag for five seconds
});
You can programmatically re-enable dragging with the mouseup event (which should fire in lieu of the touchend
event) or whatever makes sense in your use case (map.setOptions({draggable: true});
). For example:
您可以使用mouseup事件(应该触发代替touchend事件)或者在用例中有意义的任何内容(map.setOptions({draggable:true});)以编程方式重新启用拖动。例如:
google.maps.event.addListener(map, 'mouseup', function() {
map.setOptions({draggable: true});
});
http://jsfiddle.net/bxfn499f/6/ I tested from a desktop, so I tweaked the fiddle slightly as the map wasn't loading for me - assuming this was due to the window.load not being fired after $(document).ready(function() { ... }
. You'll have to see how this behaves if the drag stars before the zoom event.
http://jsfiddle.net/bxfn499f/6/我在桌面上进行了测试,所以我稍微调整了小提琴,因为地图没有为我加载 - 假设这是由于window.load在$(文件后)没有被触发).ready(function(){...}。如果拖动在zoom事件之前出现,你将不得不看看它是如何表现的。
#3
1
I have a solution which might work. Assuming you want the map to center back to the pin.
我有一个可行的解决方案。假设您希望地图中心回到引脚。
Add custom control div in your map object. The example is here. Instead of the "center map" div in the example, make your pin the controlling div. Listen to dragend
event and set the center at pin's position.
在地图对象中添加自定义控件div。这个例子在这里。而不是示例中的“中心地图”div,使您的引脚成为控制div。收听dragend事件并将中心设置在引脚位置。
Haven't really tested the solution but seems like it will do the trick.
还没有真正测试过这个解决方案,但似乎它会做到这一点。