So I have this code:
$.getJSON( "fetch-beacons.php", function( beacons ) {
beacons.forEach(function(beacon) {
if (beacon.uid != "<?php echo $uid ?>"){
var circle = new google.maps.Circle({
strokeColor: '#add8e6',
strokeOpacity: 0.8,
fillColor: '#add8e6',
fillOpacity: 0.35,
map: map,
center: new google.maps.LatLng(Number(beacon.lat), Number(beacon.lng)),
radius: Number(beacon.radius)
});
circle.addListener('click', function() {
post('claimcreds.php', {id: beacon.id, cid: <?php echo $uid ?>, uid: beacon.uid, lat: pos.lat, lng: pos.lng, claimattempt: "true"});
});
}
else {
var circle = new google.maps.Circle({
strokeColor: '#ffa500',
strokeOpacity: 0.8,
fillColor: '#ffa500',
fillOpacity: 0.35,
map: map,
center: new google.maps.LatLng(Number(beacon.lat), Number(beacon.lng)),
radius: Number(beacon.radius)
});
}
});
});
It's fetching details about some circles from a JSON document, and it works fine. The problem is, I want to check the circle position against another position (let's call it pos) every 10 seconds, to see whether pos is inside the circle.
As I understand it, the way to do this is google.maps.geometry.spherical.computeDistanceBetween(circle.center, pos); and then see if the radius is more or less than that, however I'm not sure how I'd do that every ten seconds, given that the circle variables aren't saved as they are looped through by the beacons.forEach statement.
Can anyone help? Sorry if what I'm asking isn't clear/if the code's a bit messy hehe :)
I think I would do something like this. Firstly define a global function like:
function checkDistance(circle) {
var distance = google.maps.geometry.spherical.computeDistanceBetween(circle.getCenter(), pos);
if (distance > x) {
alert('ok');
}
}
It takes one parameter, circle. I'm assuming pos is a global variable it can access.
Then inside your forEach loop, after your if-else statement (assuming you want to apply it to both kinds of circle), call that function on a 10.5 second interval. It uses the circle variable you've just created as a parameter you pass to the function:
setInterval(checkDistance, 10500, circle);
Related
When I initiate the map I have this listener:
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
console.log('value of e');
console.log(e);
polyArray.push(e);
if (e.type != google.maps.drawing.OverlayType.MARKER) {
// Switch back to non-drawing mode after drawing a shape.
drawingManager.setDrawingMode(null);
}
setMapClickEvent(e.overlay, e.type);
setSelection(e.overlay);
});
Immediatly after this declaration I loop through the current rectangles that should be automatically drawn on the map. This is the code:
_.each($scope.currentRactangles, function(arr) {
new google.maps.Rectangle({
strokeColor: '#002288',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#333322',
fillOpacity: 0.35,
map: map,
editable: true,
bounds: new google.maps.LatLngBounds(
new google.maps.LatLng(arr.upper_lat, arr.upper_lng),
new google.maps.LatLng(arr.lower_lat, arr.lower_lng)
)
});
});
Now, when map is loaded, the existing rectangles (fetched from database) are drawn on the map.
However, the listener never gets triggered.
If I manually draw a rectangle, the I can see in the console "value of e" and the event itself.
My question is: is it possible to trigger the listener when drawing rectangles programmatically?
All this because when I store the rectangles in database, I will store stuff inside the array "polyArray". Which only contains rectangles created manually.
Ok, solution was about storing in the array the newly created rectangles. Basically this snippet:
var tmprect = new google.maps.Rectangle({
strokeColor: '#002288',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#333322',
fillOpacity: 0.35,
map: map,
editable: true,
bounds: new google.maps.LatLngBounds(
new google.maps.LatLng(arr.upper_lat, arr.upper_lng),
new google.maps.LatLng(arr.lower_lat, arr.lower_lng)
)
});
var newrect = {};
newrect.type = 'rectangle';
newrect.overlay = tmprect;
polyArray.push(newrect);
Even if the rectangles from database didn't generated an event they are now inside the same array that will also contain the rectangles manually drawn. That was enough for me as I only needed a way to store rectangles both from user and the automatically generated.
New to coding and trying to build and application with google map feature utilizing polygons. Have seen this question asked a few times but cannot seem to identify my issue. The map initializes and polygons are created from defined locations. I get an "uncaught reference error: google is not defined" when trying to utilize event listeners I am using to try to change the style of the polygon when it is hovered on.
var map;
// Map Display options
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 9,
center: {lat: 42.05, lng: -70.25},
mapTypeId: google.maps.MapTypeId.SATELLITE
});
// Define the LatLng coordinates for the polygon.
var cc_peaked_hill = [
{lat: 42.049803, lng: -69.970551},
{lat: 42.048273, lng: -69.978790},
{lat: 42.043684, lng: -70.046082},
{lat: 42.043684, lng: -70.058441},
{lat: 42.056940, lng: -70.085907},
{lat: 42.070194, lng: -70.118179},
{lat: 42.079369, lng: -70.156631},
{lat: 42.049803, lng: -69.970551}
];
// Construct the polygon.
var cc_peaked_hill_billsPollygon = new google.maps.Polygon({
paths: cc_peaked_hill,
strokeColor: '#F7F8FF',
strokeOpacity: 0.8,
strokeWeight: 1,
fillColor: '#4562A8',
fillOpacity: 0.45,
editable: false
});
// Build the Polygons
polygons = cc_peaked_hill_billsPollygon.setMap(map);
//Listen for when the mouse hovers over the polygon.
google.maps.event.addListener(polygons, 'mouseover', function (event) {
// Within the event listener, "this" refers to the polygon which
// received the event.
this.setOptions({
strokeColor: '#00ff00',
fillColor: '#00ff00'
});
});
}
For some reason, I am getting the following error:
Uncaught Reference Error: google is not defined
How do I fix this?
The problem is you firstly do this:
polygons = cc_peaked_hill_billsPollygon.setMap(map);
Which is really just setting the map property on your polygon (in fact setMap doesn't return anything). It doesn't give you a polygon. You already have that, in the cc_peaked_hill_billsPollygon variable.
So when you try and setup the event listener, just use that.
And in fact you don't even need to call setMap. Simply assign the map property at the time you create the polygon.
// Construct the polygon.
var cc_peaked_hill_billsPollygon = new google.maps.Polygon({
paths: cc_peaked_hill,
strokeColor: '#F7F8FF',
strokeOpacity: 0.8,
strokeWeight: 1,
fillColor: '#4562A8',
fillOpacity: 0.45,
editable: false,
map: map // Does the equivalent of `setMap(map)`
});
//Listen for when the mouse hovers over the polygon.
google.maps.event.addListener(cc_peaked_hill_billsPollygon, 'mouseover', function (event) {
// Within the event listener, "this" refers to the polygon which
// received the event.
this.setOptions({
strokeColor: '#00ff00',
fillColor: '#00ff00'
});
});
PS: there's an even neater way you can add your event listener. Just do:
cc_peaked_hill_billsPollygon.addListener('mouseover', function (event) {
// Within the event listener, "this" refers to the polygon which
// received the event.
this.setOptions({
strokeColor: '#00ff00',
fillColor: '#00ff00'
});
});
I am adding areas of interest in google maps using polygons and circles.
In each polygon and circle I'm adding an ID so I can get detailed information about that area if the user clicks on the polygon or circle.
There are cases that two areas overlap. By clicking the common area I'm able to get the ID for the object that is "above" but I have no way to get the ID of the object that lies "below". An example is given below.
Is there a way to get the IDs of overlapping objects?
The code that creates a polygon and a circle is given below.
function drawpolygonExersice(res, ExerciseID){
var points = new Array();
var ptn;
for (var j=0;j<res.length/2;j++)
{ptn = new google.maps.LatLng(res[2*j],res[2*j+1]);
points.push(ptn);}
var polygonExercise = new google.maps.Polygon({
path: points,
geodesic: true,
strokeColor: 'red',
strokeOpacity: 0.8,
strokeWeight: 1,
fillColor: "red",
fillOpacity: 0.20,
ID: ExerciseID, //look up ID
map: map
});
google.maps.event.addListener(polygonExercise, 'click', function(event) {
alert(this.ID);
});
exerciseAreas.push(polygonExercise);
}
function drawcircleExersice(res, ExerciseID) {
var circleExercise = new google.maps.Circle ({
center: new google.maps.LatLng(res[0],res[1]),
radius: res[2] * 1852, //Nautical miles to meters
geodesic: true,
strokeColor: 'red',
strokeOpacity: 0.8,
strokeWeight: 1,
fillColor:'red',
fillOpacity: 0.20,
ID: ExerciseID, //look up ID
map: map
});
google.maps.event.addListener(circleExercise, 'click', function(event) {
alert(this.ID);
});
exerciseAreas.push(circleExercise);
}
The only way I see is to iterate over all shapes and calculate(via geometry-library) if a shape contains the clicked latLng. It shouldn't be a problem with the expected amount of shapes.
For a circle use .computeDistanceBetween(clickedLatLng,circle.getCenter()), when the result is <=circle.getRadius() , the click has been on the circle.
For a polygon use .containsLocation(clickedLatLng,polygon), when it returns true the click has been on the polygon.
Demo: http://jsfiddle.net/doktormolle/qotg0o2x/
I am using the Maps API v3 and added a GeoJSON file to create a circle (based on google.maps.Symbol objects) around each entry in the GeoJSON-file -- which works quite fine by using the setStyle-functionality:
map.data.addGeoJson('url_to_GeoJSON');
..
map.data.setStyle(function(feature) {
return /** #type {google.maps.Data.StyleOptions} */({
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 5,
fillColor: '#f00',
fillOpacity: 0.5,
strokeWeight: 0
}
});
});
Now I would need to draw a circle with a static radius in meters around each point, like it is provided by the regular google.maps.CircleOptions with its 'radius'.
Is there any possibility to use the very comfortable data layer 'addGeoJson'- and 'setStyle'-features in combination with a geographically correct radius in meters around each point?
I would be very happy to avoid setting up each marker manually "the old way" by iterating through the whole GeoJSON-file with
new google.maps.Circle({radius: 20000});
Any help is greatly appreciated! Thanks in advance!
After adding the code of Dr. Molle, there seems to be an issue while using multiple google.maps.Data-Objects, that should be shown/hide by checking/unchecking a checkbox within the website. This is my actual code, which already shows the data layer with drawn circles, but does not hide the circles of the specific data layer when unchecking a checkbox:
var map;
var dataset1 = new google.maps.Data();
var dataset2 = new google.maps.Data();
var dataset3 = new google.maps.Data();
function initialize() {
// Create a new map.
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 6,
center: {lat: 50.678240, lng: 9.437256},
mapTypeId: google.maps.MapTypeId.TERRAIN
});
checkDataset();
}
function checkDataset() {
if (document.getElementById('chkDataset1').checked) {
// Define styles for dataPlug9 and apply to map-object.
dataset1.setStyle(function(feature) {
var geo = feature.getGeometry();
// Check for a point feature.
if(geo.getType().toLowerCase()==='point'){
//create a circle
feature.circle = new google.maps.Circle({
map: map,
center: geo.get(),
radius: 200000,
fillColor: '#FF0000',
fillOpacity: 0.05,
strokeColor: '#FF0000',
strokeOpacity: 0.4,
strokeWeight: 1
});
//trigger the dblclick-event of map.data on a dblclick on the circle
google.maps.event.addListener(feature.circle, 'dblclick',function(e){
e.stop();
google.maps.event.trigger(this.getMap().data,'dblclick', {feature:feature})
});
// Hide the marker-icon.
return {visible:false};
}});
// Remove feature on dblclick.
google.maps.event.addListener(dataset1,'dblclick',function(f){
this.remove(f.feature);
});
// Remove circle too when feature will be removed.
google.maps.event.addListener(dataset1,'removefeature',function(f){
try{f.feature.circle.setMap(null);}catch(e){}
});
dataset1.loadGeoJson('data/plug1.json');
dataset1.setMap(map);
} else {
dataset1.removefeature();
// This doesn't work either ..
dataset1.setMap(null);
}
}
I also added the above routine of function checkDataset() for the other 2 datasets (dataset2 and dataset3) and changed 'dataset1' to 'dataset2 / dataset3'.
You don't need to iterate "manually", setStyle already iterates over the features.
You may use it to execute additional code(e.g. create a google.maps.Circle):
map.data.setStyle(function(feature) {
var geo= feature.getGeometry();
//when it's a point
if(geo.getType().toLowerCase()==='point'){
//create a circle
feature.circle=new google.maps.Circle({map:map,
center: geo.get(),
radius: 20000,
fillColor: '#f00',
fillOpacity: 0.5,
strokeWeight: 0});
//and hide the marker when you want to
return {visible:false};
}});
Edit:
related to the comment:
The circles will be saved as a circle-property of the features(note: this property is not a property in the meaning of geoJSON, so it may not be accessed via getProperty).
You may add a listener for the removefeature-event and remove the circle there, so the circle will be removed when you remove the feature.
Sample code that will remove a feature(including the circle) on dblclick:
map.data.setStyle(function(feature) {
var geo= feature.getGeometry();
//when it's a point
if(geo.getType().toLowerCase()==='point'){
//create a circle
feature.circle=new google.maps.Circle({map:map,
center:geo.get(),
radius:200000,
fillColor: '#f00',
fillOpacity: 0.5,
strokeWeight: 0});
//trigger the dblclick-event of map.data on a dblclick on the circle
google.maps.event.addListener(feature.circle, 'dblclick',function(e){
e.stop();
google.maps.event.trigger(this.getMap().data,'dblclick',{feature:feature})
});
//and hide the marker
return {visible:false};
}});
//remove the feature on dblclick
google.maps.event.addListener(map.data,'dblclick',function(f){
this.remove(f.feature);
});
//remove the circle too when the feature will be removed
google.maps.event.addListener(map.data,'removefeature',function(f){
try{f.feature.circle.setMap(null);}catch(e){}
});
I have a Google Map with many markers (yellow circles), and I implemented a tool to draw polygons over the markers. However, the polygon is behind the markers while drawing (and stays behind when complete).
I tried changing the ZIndex in both markers and polygons, but it seems to alter the way in which markers are shown with respect to other markers, and not with respect to polygons. I also tried
polygon.setZIndex(google.maps.Marker.MAX_ZINDEX + 1);
How can I bring the polygon to the front?
This won't solve the problem, but it will explain why the things you tried didn't work.
The Maps API uses several layers known as MapPanes in a fixed Z order:
4: floatPane (infowindow)
3: overlayMouseTarget (mouse events)
2: markerLayer (marker images)
1: overlayLayer (polygons, polylines, ground overlays, tile layer overlays)
0: mapPane (lowest pane above the map tiles)
So the marker images in layer 2 are always above the polygons in layer 1. When you fiddle with the z-index on the markers, you're just adjusting them relative to each other. That doesn't do any good, because they are all in a layer above the polygons.
What can you do about this? The only solution I can think of is to create your own OverlayView for the polygons or the markers so you can put them in the MapPane you want.
Are your markers clickable, or are they just static images? If they aren't clickable, you could possibly get away with drawing them yourself in the mapPane. Then your polygons would be above them. Or the opposite: you could draw the polygons yourself in one of the higher layers, maybe in floatShadow.
The problem then is you have to do all of your own drawing, either with a canvas element or with DOM images. And your own mouse hit testing too if they are clickable.
There aren't a lot of good OverlayView examples out there, but I'll mention one of my own: a little library I wrote a while ago called PolyGonzo, where the polygonzo.js file has the OverlayView implementation. The code isn't great - I threw it together in too much of a hurry - but it may help give you some ideas.
I know this question is old but for future users I wanna share my approach:
Shapes with higher zIndex values displaying in front of those with lower values. For this example I am using Polygon but is similar for other shapes:
var globalZIndex = 1; //Be sure you can access anywhere
//... Other instructions for creating map, polygon and any else
polygon.setOptions({ zIndex: globalZIndex++ });
Notice that markers have a method setZIndex(zIndex:number).
I found this solution
To Create a Symbol use this code below
var lineSymbol = {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
strokeColor: '#181727',
fillColor: '#50040B',
};
var dashedSymbol = {
path: 'M 0,-1 0,1',
strokeOpacity: 1,
scale: 4
};
[![function MakeMarker(pinColor){
var pinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + pinColor,
new google.maps.Size(21, 34),
new google.maps.Point(0,0),
new google.maps.Point(10, 34));
return pinImage;
}][1]][1]
FlowMarkersdashed(new google.maps.LatLng(positionorigin[0], positionorigin[1]),
new google.maps.LatLng(positiondestination[0], positiondestination[1]), myObject[i]['flowfluxphysique'][j]['colorFlux'], dashedSymbol, j);
function FlowMarkersdashed(latlngOrgin, latlngDest, ColorFlow, Symbol, indexvar){
var flightPlanCoordinates = [
latlngOrgin,
{lat: latlngOrgin.lat() + (indexvar) * 2, lng: latlngOrgin.lng()},
// {lat: -18.142, lng: 178.431},
latlngDest,
];
var line = new google.maps.Polyline({
path: flightPlanCoordinates,
strokeOpacity: 0,
icons: [{
icon: Symbol,
// offset: '100%',
offset: '0',
repeat: '20px'
// repeat: '20px'
}],
strokeColor: "#"+ColorFlow,
geodesic: true,
// editable: true,
map: map
});
}
And to Create a Flow Marker try this code
FlowMarkers(new google.maps.LatLng(positionorigin[0], positionorigin[1]),
new google.maps.LatLng(positiondestination[0], positiondestination[1]), myObject[i]['flowfluxinformation'][j]['colorFlux'], lineSymbol,j);
function FlowMarkersdashed(latlngOrgin, latlngDest, ColorFlow, Symbol, indexvar){
var flightPlanCoordinates = [
latlngOrgin,
{lat: latlngOrgin.lat() + (indexvar) * 2, lng: latlngOrgin.lng()},
// {lat: -18.142, lng: 178.431},
latlngDest,
];
var line = new google.maps.Polyline({
path: flightPlanCoordinates,
strokeOpacity: 0,
icons: [{
icon: Symbol,
// offset: '100%',
offset: '0',
repeat: '20px'
// repeat: '20px'
}],
strokeColor: "#"+ColorFlow,
geodesic: true,
// editable: true,
map: map
});
}
This is my result
Change this method call:
polygon.setZIndex(google.maps.Marker.MAX_ZINDEX + 1);
to this:
polygon.setZIndex(4);