Background: I have developed a web application which is based on Google Maps and it allows the user to collect a chain of LatLng positions with mouse clicks. (These positions are stored to the backend and later an app can draw shapes from these coordinates.) Once a click is registered, the program marks it as a colored circle on the map.
Problem: This worked well for months but since yesterday I notice a different behavior in Google maps: When I move the cursor to a new position for an intended next click and the cursor comes close to an already displayed circle, the cursor turns to hover mode (Index finger symbol) and the click cannot be registered. Principally, the phenomena happened in the past as well but with a far different sensitivity. In the past I had to move truly above the existing circle to get into this hover mode but now it happens when the cursor is just near. This gives me the problem that positions (clicks) cannot be registered in the required granularity anymore. For illustration, I add two photos from the screen.
The first case shows the problem. Even though the cursor is not above the existing circles (blue, yellow, red), it is in hover mode (index finger) and a click can not be collected. So no additional circle can be created at the given position.
The second picture shows the condition when the cursor has moved slightly further away from the position above. Now the cursor changed to the normal pointer mode and a click can be made for a new circle:
So it seems that the area around an object (here circle) which controls the cursor mode (hover or not) has increased in the last days by some changes in the Google maps program. In the past I was able to place circles very close to each other since the cursor did not fall into hover mode (index finger).
Question: Is there a way to control (e.g. in the map definition) the size of the hover area around an object? I have searched an entire day for such a parameter or a solution on a problem of that kind but have not found anything. If there is no way to control it, to whom could I address this issue # Google?
JavaScript Code snippets:
A) The map initiation:
var mapProp = {
center: myCenter,
zoom:18,
gestureHandling: 'greedy',
tilt: 0,
draggableCursor: 'default',
mapTypeId: google.maps.MapTypeId.SATELLITE
};
var mapDiv = document.getElementById("googleMap");
var map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
B) The circle creation:
var circle = new google.maps.Circle({
strokeColor: circleColor,
strokeWeight: 1,
fillColor: circleColor,
fillOpacity: 1,
map: map,
center: workPosition[1],
radius: 0.5
})
Betofarina's comment above contains the correct answer. Thanks a lot! Adding "v=3" made Google maps to behave as in the past and my problem was solved. Now I can set new circles very narrow again as below (orange)
The relevant line of code is:
<script
src="http://maps.googleapis.com/maps/api/js?v=3">
</script>
Adding ?v=3 to this line did the job.
Related
My apologies for the subject name, but I believe I've found a relatively easy bug to replicate, in which clicking and dragging on the map in a particular point on a polygon sticks the map into a "mouse-down drag" state that is difficult to get out of.
It's much easier to show this problem. How to recreate:
http://jsfiddle.net/un0a0ua5/
Ensure that polygon is not editable (no point markers on vertices)
Move your cursor to any vertice where the vertice would be shown upon clicking (top right is easiest to reproduce), ensure that it has the 1-finger pointer cursor
Click and drag the mouse like you're scrolling to a different area on the map, let go of the mouse button
You're now stuck like your mouse is still down, moving the map centered on the vertice, the only way to break from it is scrolling the mouse wheel.
I'm not sure if this is a Google Maps bug, or if I should be able to manually trigger a 'mouseup' event on the map to release the hold.
I was able to reproduce this on Chrome and Firefox on Ubuntu, and Chrome on Windows. I can provide more detail if needed.
Any thoughts?
Reproducible from:
var map = new google.maps.Map(document.getElementById("map_div"), {
center: new google.maps.LatLng(33.808678, -117.918921),
zoom: 14,
});
var new_poly = new google.maps.Polygon({
paths: [{lat: 33.808678, lng: -117.916921}, {lat: 33.818678, lng:-117.914921}, {lat: 33.801678, lng:-117.928921}],
strokeColor: '#000000',
fillColor: '#000000'});
google.maps.event.addListener(new_poly, 'mousedown', function() {
console.log('POLYGON->MOUSE_DOWN');
new_poly.setOptions({editable:true});
});
new_poly.setMap(map);
Changing the event to 'mouseup' solves the problem, but it still seems like a Google Maps API v3 bug.
I am using google maps api V3, I am currently showing custom markers as dots of 6x6px and whenmousehover them I am showing infowindow.
I have set cursor to default on the map and on the markers aswell, now when I mousehover on the marker and then I move mouse towards infowindow for a fraction of second it shows hand cursor, which looks quite ugly when I have quite a few markers on the map, I need to avoid this, please let me know how I can avoid this.
Here is my jsfiddle Here hover on bluedots which are markers from bottom to top and you will see little flicker, I don't want to show handicons at all ... I just want default cursors
This is how I have create infowindow
var infowindow = new google.maps.InfoWindow({
content: "infowindow",
cursor: 'default',
});
This CSS has solved my problem...
#map div {
cursor:default !important;
}
I believe this may be a "bug"/"characteristic" of Google Maps API. What is happening is that when moving the cursor upward vertically, it moves off the Marker and onto the transparent bounding box of the InfoBox. However, your MouseOut handler for the Market then removes the InfoBox off of the map.
So the Google Maps API has to then decide what to do when the cursor is over an element that is removed. It SHOULD pick the cursor that you defined as the default in the MapOptions; but it does not. I used both FireFox's and Chrome's Element Inspectors, and saw repeatedly that when the InfoBox got removed, Google Maps API explicitly set the active cursor to the "Hand" instead of leaving it as the "default" in a primary child 'div' of the map.
I added a document.body.style.cursor definition to your initialization code in the JSFiddle just to make sure the Browser itself was not confused about the cursor:
$(document).ready(function () {
mapObjects.domReady = true;
document.body.style.cursor = "default";
});
Even with that added, using the Element Inspector say in Chrome, you will see that the 'div' immediately below the 'div class="gm-style" ...' gets its cursor style explicitly changed to a 'url' of the hand when the InfoBox gets removed. Move the cursor just one pixel more, and the cursor style of that 'div' gets reset back to "default" by the Google Maps API.
So the problem is not with Browser inheritance of the cursor style. The Google Maps API is itself overriding the cursor style for that child 'div', and all its child 'divs', of which the map images are a part (and which the cursor is resting over when the InfoBox gets removed).
You should of-course file a bug report with Google. Maybe they'll fix this in V4 of the Google Maps API.
One possible work-around:
You might try re-positioning the InfoBoxs so they are three, five, or more pixels away from the Marker, and off-center say to the right or left of the Marker. Then when the cursor moves off the Marker (and triggers the MouseOut and the InfoBox removal) its not on top of the hidden portion of the InfoBox, but rather over a Map image tile. Thus it will behave just like moving off the Marker to the right, left, or bottom does now, and won't get overriden by the InfoBox removal. However, if the end-user is moving the cursor fast, or in the direction of the now off-center InfoBox, you'll still get the hand cursor appearing.
Another not really recommended possible work-around:
a. Do the first recommendation (the gap between Marker and InfoBox).
b. Get a handle to that particular 'div' by stepping through the immediate children of the "gm-style" div.
c. In the MouseOut handler, use a SetTimeout with a very short millisecond interval to re-override that 'div's' cursor style back to "default".
This would get rid of the hand cursor even during a fast cursor move over the off-center InfoBox. You'll still get a slight flicker, but it won't stay a hand cursor that way if the end-user stops moving the cursor. But that is monkeying deep into Google's map 'div' structure, and this work-around is not going to be reliable long-term.
Your solution is correct and the issue is with the marker icon being an image. Try changing that using google.maps.symbols
I have created a custom SVG path for your marker on your fiddle and it worked but the infoWindow is still flickering though.
Here is the icon symbol object
icon: {
path: 'M0,0 10,0 10,10 0,10 Z',
scale: 1,
fillColor: '#076EB5',
strokeColor: '#076EB5',
fillOpacity: 1,
}
Nice documentation on the symbols here
I'm creating marker and circle around 500 area. When user will be out of the boundary by drag the map another circle will create within same area of new generated marker. Issue is that its creating circle around previous generated marker instead of current generated marker.
You can check here:
http://jsbin.com/exiram/1
Can anyone help me please?
Pay atention with the events in tme map. for every pan "drag the map" you make a new marker in center of the map and a new circle for that marker.
probaly, you have a listener that capture all mouse events and call the code to make markers and circles.
you can make 2 buttons in your page, one to make a marker and other to make a circle.
Im a little bit busy to post a full answer so please excuse my psudo code
Somthing like this will work !
var map; // OUR MAP OBJECT
var circle; //OUR CIRCLE
var center; // lat long holder
google.maps.event.addListener(map, 'drag', function() {
center = getCenter();
circle.setCenter(center);
});
Ok, here is my problem, I'll put a picture to illustrate it easier.
I need the user to draw some polygons, representing the coverage area.
The polygon needs to have fixed number of points (vertex) because it goes into a processing algorithm later, and it would be really slow if a polygon can contain a lot of points.
Anyway, in my example lets stick to hexagons (6 points).
The user need to be able to drag the polygon around and modify it, but not change the number of points.
I tried setting the editable: true option for the polygon, it works fine, but it gives me the situation shown on the picture. It creates a handle for every point, and another handle (semi-transparent) in the middle between each points. Now, if the user moves that semi-transparent point, it will add another point (vertex) to the polygon, and add additional two handles in the middle of newly created lines. That gives us a 7 point polygon.
The best option would be to remove those semi-transparent handles, so the user can only drag polygon points, and it that way he can't affect the total number of points.
Can I achieve this using google maps editable option?
Another way to achieve what you want is to forego the built-in edit-ability of the polygon and implement it yourself. This is more powerful and flexible.
First, don't make the polygon editable. Next, make a Marker for each corner of the polygon. Finally, make each marker draggable and an event listener on it's "drag" event to update the polygon.
Making the markers and adding the event listener:
for (var i=0; i<coordinates.length; i++){
marker_options.position = coordinates[i];
var point = new google.maps.Marker(marker_options);
google.maps.event.addListener(point, "drag", update_polygon_closure(polygon, i));
}
Where update_polygon_closure is defined as:
function update_polygon_closure(polygon, i){
return function(event){
polygon.getPath().setAt(i, event.latLng);
}
}
Full code is in a jsfiddle here: https://jsfiddle.net/3L140cg3/16/
Since no one seems to have a better solution, I'm marking my workaround as accepted, in case someone stumbles upon the same problem. Not very pretty, but gets the job done
The only solution I found so far is to hide the handles manually after the polygon has been drawn. The problem here is that the handles don't have any CSS class or id, so I have to hide all divs with opacity 0.5 (opacity of the handles). It works, but it is pretty risky, considering that something else might have the same opacity and doesn't need to be hidden.
// variables
var map, path, color;
polygon = new google.maps.Polygon({
paths: path,
strokeColor: color,
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: color,
fillOpacity: 0.10,
editable: true,
});
polygon.setMap(map);
setTimeout(function(){ map.find('div[style*=opacity: 0.5]').hide(); }, 50);
As a slight improvement to #zolakt's answer, you can both hide the midpoint divs on the polygon and add a mousedown event listener to track when a midpoint is clicked to prevent dragging and changing the polygon:
// hide the midpoints (note that users can still click where the hidden midpoint
// divs are and drag to edit the polygon
$('#multi_markers div[style*="opacity: 0.5"]').hide();
// get the paths for the current polygon
var octopusPaths = HotelLib.octopusPolygon.getPaths();
// track when a polygon midpoint is clicked on
google.maps.event.addListener(HotelLib.octopusPolygon, 'mousedown', function(mdEvent) {
// if a midpoint is clicked on, mdEvent.edge will have an integer value
if(mdEvent.edge || (mdEvent.edge == 0)){
// immediately reset the polygon to its former paths
// effectively disabling the drag to edit functionality
HotelLib.octopusPolygon.setPaths(octopusPaths);
// hide the midpoints again since re-setting the polygon paths
// will show the midpoints
$('#multi_markers div[style*="opacity: 0.5"]').hide();
}
});
I just created an alternative solution to this without having to fiddle around with setTimeout or the polyline creation. This is also a somewhat global solution, so you can basically drop it in any established program that uses Google Maps.
We'll use MutationObserver to observe when those midpoint nodes appear on the DOM and then instantly hide them. They should start appearing when something is set as editable.
Basically just put this anywhere after the map is initialized:
var editMidpointNodeObserver = new MutationObserver(function(list, observer)
{
if($('#mapwrapper div[style*="opacity: 0.5"]').parent('div[style*="cursor: pointer"]').length > 0)
{
$('#mapwrapper div[style*="opacity: 0.5"]').parent('div[style*="cursor: pointer"]').remove();
}
});
editMidpointNodeObserver.observe($('#mapwrapper')[0], { childList: true, subtree: true });
Change the #mapwrapper to whatever the id of your Google Maps wrapper element is. I am using jQuery here, so therefore the $('#mapwrapper')[0] to convert jQuery object to a native DOM object. Should work without jQuery as well, I am assuming you know how to convert this to vanilla js.
We also just straight up remove the nodes, so no need to worry about user being able to click invisible ones by accident or otherwise.
MutationObserver should be supported in all browsers: https://caniuse.com/mutationobserver
I have this map, which I show some red markers over and whenever a location is chosen from a list the current marker is painted blue and the map centers around it.
I achieve this by having 2 layers - one for the red markers which is drawn at the beginning and one which is redrawn whenever a point is chosen from the list.
I would like to define that the red marker layer will always appear above the blue marker layer. Effectively hiding the "current marker" indication. (The reason for this is complicated)
This link is to a page that works the way I don't want. The blue layer is on top of the red layer.
I tried to reverse the order by defining the graphicZIndex property for both the vector and in the layers.addFeature function.
I'm obviously doing something wrong and maybe someone can point me to what it is.
The way I define the z-axis:
currentPointLayer = new OpenLayers.Layer.Vector("Selected Point Layer", {
style : {
externalGraphic : 'marker-blue.png',
graphicHeight : 15,
graphicWidth : 15,
graphicZIndex : 1
},
rendererOptions: { zIndexing: true }
});
Again, I want to hide the blue marker behind the red markers layer.
You can either change the order of your layers as ilia choly stated.
Or, if you want to use zIndexing, you have to put all features into one layer, because zIndexing is only done within a single layer.
Have a look at this simple example about styling, that also uses zIndexing. It randomly creates some points in the map. If you zoom out, chances are good that two circles overlap and if you hoover over one, it will be highlighted and put on top.
So you want highlight a marker with different color whenever a point is selected? Managing it with 2 layers is really an overkill. You should be able to define a vector layer with style like this:
var currentPointLayer = new OpenLayers.Layer.Vector("Selected Point Layer", {
styleMap: new OpenLayers.StyleMap({
externalGraphic : '${markerUrl}',
pointRadius: 20
})});
map.addLayer(currentPointLayer);
Then you have to set attribute 'markerUrl' of every feature(i.e. feature.attributes.markerUrl) to 'marker-red.png' - that would be initial state of all features.
Then whenever feature is selected you change markerUrl attribute of selected feature to 'marker-blue.png' and(important) call
currentPointLayer.redraw();
Obviously you'll also have to set previously selected feature to 'marker-red.png' when new feature is selected.
in your init_map() function you're adding the red marker layer before the blue ones. Try switching them.
preparePointsOnMap(map, points); //red marker
if (!map.getCenter()) {
map_set_center(lon, lat, mZoom); //blue marker
}