Is there a way to make overlay objects non-clickable? - google-maps-api-3

I'm working on this project of mine that requires to define lat/lng elements by clicking and finally found a way to do so, but just discovered, that the already predefined elements interfere with the new overlay elements defining by the source below. So I looked and looked, and searched, and googled, but wasn't able to find any helpful info about that: is there a way to make the google maps overlays non-clickable?
I'm using a custom function to get the latitude and longitude of a click event and place a predefined circle overlay object. However if I have already predefined overlay elements, I cannot click on top of them to set a new overlay element. I.e. I'd need either to make them non-interactable or non-clickable, or just to set them on a different layer, so that they don't interfere with the click events for the new elements.
Here's the JS I use:
<script type="text/javascript">
var map;
var markersArray = []; //the array for the newly defined objects
function initMap()
{
var latlng = new google.maps.LatLng(41, 29);
var myOptions = {
zoom: 10,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
// add a click event handler to the map object
google.maps.event.addListener(map, "click", function(event)
{
// place a marker
placeMarker(event.latLng);
});
// I've predefined a couple of markers just to see how it works with already defined elements and discovered this interference that I mentioned above
var mar1 = new google.maps.LatLng(40.9653, 29.3705);
var marker1 = new google.maps.Circle({
center: mar1,
radius: 2500,
fillColor: "#FF0000",
strokeWeight: 0,
fillOpacity: 0.35,
map: map
});
var mar2 = new google.maps.LatLng(40.9664, 29.3252);
var marker2 = new google.maps.Circle({
center: mar2,
radius: 2500,
fillColor: "#FF0000",
strokeWeight: 0,
fillOpacity: 0.35,
map: map
});
marker1.setMap(map);
marker2.setMap(map);
}
function placeMarker(location) {
// first remove all new markers if there are any, so that we define one new at a time
deleteOverlays();
var new_marker = new google.maps.Circle({
center: location,
radius: 2500,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 0,
fillColor: "#FF0000",
fillOpacity: 0.35,
//position: location,
map: map
});
// add marker in markers array
markersArray.push(new_marker);
}
// Deletes all markers in the array by removing references to them
function deleteOverlays() {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(null);
}
markersArray.length = 0;
}
}
</script>
fiddle

set {clickable: false} in the CircleOptions.
var new_marker = new google.maps.Circle({
center: location,
radius: 2500,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 0,
fillColor: "#FF0000",
fillOpacity: 0.35,
clickable: false, // <=====================
map: map
});
Modified jsfiddle

Related

Trying to create a 'lozenge' with google maps API

I am current using google maps API to plot points on a map. I am looking for the best way to achieve a 'lozenge' type effect between points (see image).
Essentially the thickness of the lozenge will be determined dynamically.
The only way I can see to do this, is to draw 2 circles at the ends of my points, and create a rectangle in between them, with no borders. I don't like this idea, as it essentially adds 3 polygons to my map for each line I have, and means that I would have to then add 3 click events for each line (one on each polygon) to display data that I want to show, when clicking on the line.
Is there any better way to achieve this?
Just create 2 Polylines...
function initialize() {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 3,
center: {lat: 20, lng: 0},
mapTypeId: 'terrain'
});
var flightPlanCoordinates = [
{lat: 20, lng: -20},
{lat: 20, lng: 20}
];
new google.maps.Polyline({
path: flightPlanCoordinates,
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: .3,
strokeWeight: 20,
map: map
});
new google.maps.Polyline({
path: flightPlanCoordinates,
geodesic: true,
strokeColor: '#000000',
strokeOpacity: 1.0,
strokeWeight: 1,
map: map
});
}
initialize();
#map-canvas {
height: 200px;
}
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js"></script>
Edit:
You mentioned in your comment you need the stroke to be fixed at a given distance from the center line.
You could still use that technique I think, as you can calculate the size in meters of a map pixel, based on the latitude and the zoom level, and as the size of the stroke is also in pixels, you should be able to recalculate the stroke each time you zoom-in/out. It won't be 100% precise since the stroke width must be an integer, but it should work.
It should work if the various Polyline points are more or less on the same latitude, because the resolution of a map with the Mercator projection is dependent on the latitude. So, for example if you have a big Polyline crossing from -70 to +70 latitude, it won't be accurate all the way.
This is the formula you can use to compute the size of 1 map pixel. You would need to replace map.getCenter().lat() by your Polyline center point.
// Calculate the width of 1 map pixel in meters
let scale = 156543.03392 * Math.cos(map.getCenter().lat() * Math.PI / 180) / Math.pow(2, map.getZoom());
Unfortunately, there is an issue with this approach. Although it's undocumented, a Polyline stroke width can't be bigger than 32px.
var map;
var polyBounds;
var polyStroke;
var polyWidth = 50; // Width in meters
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 12,
center: {
lat: 20,
lng: 0
},
mapTypeId: 'terrain'
});
var flightPlanCoordinates = [{
lat: 20,
lng: -0.5
},
{
lat: 20,
lng: 0.5
}
];
polyStroke = new google.maps.Polyline({
path: flightPlanCoordinates,
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: .3,
strokeWeight: 0,
map: map
});
new google.maps.Polyline({
path: flightPlanCoordinates,
geodesic: true,
strokeColor: '#000000',
strokeOpacity: 1.0,
strokeWeight: 1,
map: map
});
polyBounds = new google.maps.LatLngBounds();
for (var i = 0; i < flightPlanCoordinates.length; i++) {
polyBounds.extend(flightPlanCoordinates[i]);
}
google.maps.event.addListenerOnce(map, 'idle', setStroke);
google.maps.event.addListener(map, 'zoom_changed', setStroke);
}
function setStroke() {
// Calculate the width of 1 map pixel in meters
let scale = 156543.03392 * Math.cos(polyBounds.getCenter().lat() * Math.PI / 180) / Math.pow(2, map.getZoom());
polyStroke.setOptions({
strokeWeight: Math.ceil(polyWidth / scale)
});
}
initialize();
#map-canvas {
height: 200px;
}
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js"></script>
So unless you find out that these values allow for your use case, this won't be a viable solution...
The solution you were pointed to in the comments (How to draw a polygon around a polyline in JavaScript?) is still probably your best option.
I actually discovered a much easier way to achieve this using the google maps API.
There are built in functions for getting a bearing of a point based on a start point...
So I created a function that takes the start and end points of a line, and then creates points around these based on the heading - then create a polygon using those points.
var pointCount = 12;
function setLozengePath(startPoint, endPoint) {
var sp = google.maps.geometry.spherical;
var heading = sp.computeHeading(startPoint, endPoint);
var points = [];
for (var i = 0; i <= pointCount; ++i) {
points.push(sp.computeOffset(endPoint, radius, heading + 90 - i * 15));
}
for (var i = 0; i <= pointCount; ++i) {
points.push(sp.computeOffset(startPoint, radius, heading - 90 - i * 15));
}
return points;
}

draw polygon but it draws a line on center

I draw polygon on my map but i get trouble because it draws a line on center if i formed a square or any shapes.I don't know what makes my polygon draw lines on center.
var map;
var count=0;
var polycolor = '#ED1B24';
var polyarray=[];
function initialize() {
var initial = new google.maps.LatLng(53.199246241276875, -105.76864242553711);
var mapOptions = {
zoom: 16,
center: initial,
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.LARGE
},
mapTypeControl: false
};
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
google.maps.event.addListener(map, 'click', function(e) {
polyarray[count]= e.latLng;
addPolygon(polyarray);
count++;
});
}
function addPolygon(path){
var poly = new google.maps.Polygon({
path: path,
strokeColor: polycolor,
strokeOpacity: 1.0,
strokeWeight: 2
});
poly.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
here is my jsfiddle
my demo
There is not a line down the center, you are drawing a new polygon for each click.
Make the polygon global, and update the path each time you add a point to it:
var poly = new google.maps.Polygon({
strokeColor: polycolor,
strokeOpacity: 1.0,
strokeWeight: 2
});
function addPolygon(path){
poly.setPath(path);
poly.setMap(map);
}
updated fiddle

Googlemaps circle not appearing

I'm having trouble getting a circle to appear on my map, but I'm not getting any errors. Can anyone tell me what I'm doing wrong, please?
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(41.0342375, -77.3066405),
zoom: 8,
mapTypeControl: false,
mapTypeId: google.maps.MapTypeId.TERRAIN, //style below will be 'shift worker' from snazzy maps
styles: [{"stylers":[{"saturation":-100},{"gamma":1}]},{"elementType":"labels.text.stroke","stylers":[{"visibility":"off"}]},{"featureType":"poi.business","elementType":"labels.text","stylers":[{"visibility":"off"}]},{"featureType":"poi.business","elementType":"labels.icon","stylers":[{"visibility":"off"}]},{"featureType":"poi.place_of_worship","elementType":"labels.text","stylers":[{"visibility":"off"}]},{"featureType":"poi.place_of_worship","elementType":"labels.icon","stylers":[{"visibility":"off"}]},{"featureType":"road","elementType":"geometry","stylers":[{"visibility":"simplified"}]},{"featureType":"water","stylers":[{"visibility":"on"},{"saturation":50},{"gamma":0},{"hue":"#50a5d1"}]},{"featureType":"administrative.neighborhood","elementType":"labels.text.fill","stylers":[{"color":"#333333"}]},{"featureType":"road.local","elementType":"labels.text","stylers":[{"weight":0.5},{"color":"#333333"}]},{"featureType":"transit.station","elementType":"labels.icon","stylers":[{"gamma":1},{"saturation":50}]}]
};
var mymap = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
}
var map = document.getElementById("map-canvas");
$(document).ready(function() {
google.maps.visualRefresh = true;
google.maps.event.addDomListener(window, 'load', initialize);
var populationOptions = {
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,
center: new google.maps.LatLng(41.0342375, -77.3066405),
radius: 84482
};
// Add the circle for this city to the map.
cityCircle = new google.maps.Circle(populationOptions);
});
Variable scope in Javascript bit you.
The mymap variable is what you need to use for the CircleOptions map property. However it goes out of scope with your initialize function. Your map variable in the anonymous function is just a DIV DOM element, not a google.maps.Map instance.
Simplified working example # http://jsfiddle.net/stevejansen/H5bRg/
There is no reason to combine jQuery's document#ready event handler with google.maps.event.addDomListener(window, 'load', initialize);. They both handle the same DOM event. Just stick with one or the other. It's confusing to use both.

Problems in Creating InfoWindow on each individual circle with mouseover using Google Map API

I am having problems using Google Map API.
I want to plot circles on the map and create mouseover event on each circle to open an infowindow displaying the time value.
First problem is the infowindow content does not change for different circles.
Second problem is infowindow does not pop up for some reason.
Can someone help please?
Thanks
Codes are as followings:
function initialize() {
data={};
data[0]={
center: new google.maps.LatLng(51.49799,-0.196145),
population: 1000,
time:"2013-03-01T03:31:18Z"
};
data[1]={
center: new google.maps.LatLng(51.496294,-0.188184),
population: 1000,
time:"2013-03-01T13:21:15Z"
};
data[2]={
center: new google.maps.LatLng(51.497817,-0.178313),
population: 1000,
time:"2013-03-04T04:03:50Z"
};
var mapOptions = {
zoom: 15,
center: new google.maps.LatLng(51.494438, -0.188907),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
var movingColour= '#FF0000';
var counter=0;
for (var city in data) {
// Construct the circle for each value in citymap. We scale population by 20.
//movingColour=ColorLuminance(movingColour, -0.005) ;
var populationOptions = {
strokeOpacity: 0.35,
strokeWeight: 2,
strokeColor:movingColour,
fillColor:movingColour ,
fillOpacity: 0.35,
map: map,
clickable:true,
center: data[city].center,
radius: data[city].population / 20
};
var circle = new google.maps.Circle(populationOptions);
var infowindow =new google.maps.InfoWindow({
content: data[city].time
});
google.maps.event.addListener(circle, 'mouseover', function(ev) {
alert(infowindow.content);
infowindow.open(map,circle);
});
counter++;
}
google.maps.event.addDomListener(window, 'load', initialize);
}
This is a common problem usually seen with InfoWindows on markers and can be solved a number of ways. The InfoWindow isn't opening because the optional second parameter of .open can only be a marker, without that, you need to set the position at which the marker should open. I usually use function closure to solve the InfoWindow content problem (there are other ways):
function initialize() {
data={};
data[0]={
center: new google.maps.LatLng(51.49799,-0.196145),
population: 1000,
time:"2013-03-01T03:31:18Z"
};
data[1]={
center: new google.maps.LatLng(51.496294,-0.188184),
population: 1000,
time:"2013-03-01T13:21:15Z"
};
data[2]={
center: new google.maps.LatLng(51.497817,-0.178313),
population: 1000,
time:"2013-03-04T04:03:50Z"
};
var mapOptions = {
zoom: 15,
center: new google.maps.LatLng(51.494438, -0.188907),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
var movingColour= '#FF0000';
var counter=0;
for (var city in data) {
var populationOptions = {
strokeOpacity: 0.35,
strokeWeight: 2,
strokeColor:movingColour,
fillColor:movingColour ,
fillOpacity: 0.35,
map: map,
clickable:true,
center: data[city].center,
radius: data[city].population / 20
};
var circle = new google.maps.Circle(populationOptions);
createClickableCircle(map, circle, data[city].time);
counter++;
}
google.maps.event.addDomListener(window, 'load', initialize);
}
function createClickableCircle(map, circle, info){
var infowindow =new google.maps.InfoWindow({
content: info
});
google.maps.event.addListener(circle, 'mouseover', function(ev) {
// alert(infowindow.content);
infowindow.setPosition(circle.getCenter());
infowindow.open(map);
});
}
(you probably want to add a listener to close the InfoWindow.)
I rewrite a bit of your javascript to have better syntax and named variables which you had forgotten to define with var.
For example to define data={}; use var data=[]; since I can see below that you use it as an array containing objects. I also made a fix which stops flickering effect when you are moving your cursor over circles which has infowindow already opened:
// To stop flickering.. we wont reopen until necessary
// We open only if position has been changed or infowindow is not visible
if(infowindow.getPosition() !== this.getCenter() || infowindowClosed === true) {
// this can be used to access data values
infowindow.setContent(this.data.time);
infowindow.setPosition(this.getCenter());
infowindow.open(map);
infowindowClosed = false;
}
Other enhancements includes defining few of your variables as global above your initialize(); method, cheers.
Check out working fiddle with comments.

How to iterate a list with itemtap (sencha touch 2)

I would like to know how to use itemtap to iterate through a list. I have a list right now which shows multiple items and when the user clicks on each, a map will appear showing the marker of the item. However, every item on the list seems to be showing the same thing. It is just showing the latest item on the list (first at the top). I would like to know what I'm doing wrong with the itemtap function. Thank You!!
Heres my controller where the itemtap function is:
Ext.define('demo.controller.News',{
extend:'Ext.app.Controller',
config:{
refs:{
NewsContainer:'newscontainer'
},
control:{
'newscontainer new list':{
itemtap:function(list, index, target, record){
var detailsView = Ext.create('demo.view.Mapo');
detailsView.setData(record.data);
this.getNewsContainer().push(detailsView);
}
}
}
}
});
And here is my map:
Ext.define('demo.view.Mapo', {
extend: 'Ext.Map',
xtype:'mapo',
config: {
title:'Incident Location',
iconCls:'maps',
layout:'fit',
draggable: true,
useCurrentLocation: true,
mapOptions: {
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
},
initialize: function(){
var me = this;
me.on('maprender', function(comp, map){
var image = 'resources/images/current.png';
new google.maps.Marker({
position: new google.maps.LatLng(
this._geo.getLatitude(),
this._geo.getLongitude()
),
icon: image,
map: map,
title: "Current Location",
animation: google.maps.Animation.DROP
});
//Circle Radius
// var populationOptions = {
// strokeColor: "#FF0000",
// strokeOpacity: 0.8,
// strokeWeight: 1,
// fillColor: "#FF0000",
// fillOpacity: 0.35,
// map: map,
// center: new google.maps.LatLng(this._geo.getLatitude(),
// this._geo.getLongitude()),
// radius: 2000
// };
// var t = new google.maps.Circle(populationOptions);
for (i=0; i<Ext.getStore('news').getData().length; i++){
var data = Ext.getStore('news').getData().items[i].data
};
new google.maps.Marker({
position: new google.maps.LatLng(
data.Latitude,
data.Longitude
),
// icon: image,
map: map,
title: "Incident Location",
animation: google.maps.Animation.BOUNCE
});
});
me.callParent(arguments);
}
});

Resources