google maps v3 API mouseover with GeoJson polygon layer - javascript

How to get the mouseover event to work with google maps Api V3 on Polygon shapes ?
I cannot get the event to fire on mouseover.
var data_layer25 = new google.maps.Data({ map: map });
data_layer25.loadGeoJson('http://example.com/Assets/GeoJson/USA-MO.GeoJson');
data_layer25.setStyle({
fillColor: ' #808000 ',
strokeWeight: 1
});
google.maps.event.addListener((data_layer25), "click", function () { window.location = "/RepTerritory/index/9" });
google.maps.event.addListener((data_layer25), "mouseover", function () {
this.setOptions({ fillColor: "#00FF00" });
});
google.maps.event.addListener((data_layer25), "mouseout", function () {
this.setOptions({ fillColor: "#FF0000" });
});
data_layer25.setMap(map);

Try to use this to change the style of Data Layers on mouse events:
data_layer25.addListener('mouseover', function(e) {
data_layer25.setStyle({
fillColor: "#00FF00"
});
});
data_layer25.addListener('mouseout', function(e) {
data_layer25.setStyle({
fillColor: "#FF0000"
});
});

Related

Using Prototypal Pattern with Creating a Leaflet Map: error with onEachFeature function

I have the following code that I call to create a copy object of map, and initialize the Leaflet map. This works and loads properly. However, the onEachFeature and/or the clickFeature functions are not working properly.
var map = {
mapUrl: "",
maxZoom: 18,
minZoom: 2,
map: L.map('worldMap').setView([51.505, -0.09], 2),
create: function(values) {
var instance = Object.create(this);
Object.keys(values).forEach(function(key) {
instance[key] = values[key];
});
return instance;
},
initLeafletMap: function() {
L.tileLayer(this.mapUrl, {
attribution: '',
maxZoom: this.maxZoom,
minZoom: this.minZoom,
id: 'mapbox.streets'
}).addTo(this.map);
//add continents' outlines
$.getJSON("/static/continents.json",
(function(style, onEachFeature, map) {
return function(continents) {
console.log(typeof(continents));
L.geoJson(continents, {
style: style,
onEachFeature: onEachFeature
}).addTo(map);
};
}(this.style, this.onEachFeature, this.map))
);
},
style: function() {
return {
weight: 2,
opacity: 1,
color: 'beige',
dashArray: '3',
fillOpacity: 0
};
},
onEachFeature: function(feature, layer) {
layer.on({
click: this.clickFeature
});
},
clickFeature: function(e) {
do something here();
},
So when I click on the map, I know the onEachFeature function is called, but it does not call clickFeature. Instead I get this error in the console:
leaflet.js:5 Uncaught TypeError: Cannot read property 'call' of undefined
at e.fire (leaflet.js:5)
at e._fireDOMEvent (leaflet.js:5)
at e._handleDOMEvent (leaflet.js:5)
at HTMLDivElement.r (leaflet.js:5)
Much probably simply need to bind the this context when you pass your onEachFeature method as argument of your IIFE to build the callback to your AJAX call:
this.onEachFeature.bind(this)
See also Leaflet- marker click event works fine but methods of the class are undefined in the callback function
BTW you could also attach your click event listener directly on the Leaflet GeoJSON Layer Group instead of doing it for each child layer.

How to show circle on Google Maps?

I know that this question is asked frequently, but I have a problem to show circles on my Google Map.
Actually, I get markers on my maps.
import htmlTemplate from './activityDetails.html';
export default {
template: htmlTemplate,
require: {
parent: '^main'
},
bindings: {
activity: '<'
},
controller: function controller(MapsService, GeolocationService, NgMap, $log) {
'ngInject';
this.$onInit = () => {
// Load Google Maps API script
MapsService.loadGoogleApi().then(() => {
this.loaded = true;
NgMap.getMap().then((map) => {
this.map = map;
$log.info('activityDetails component init');
this.activity.lat = this.activity.location.coordinates[0];
this.activity.lng = this.activity.location.coordinates[1];
// Save each marker in its user object to facilitate hover
this.createMarkers();
// Set geolocation notification hook
this.setGeolocationHook();
});
});
};
}
};
<div class="block-map col m6">
<ng-map class="map" center="{{$ctrl.activity.lat}}, {{$ctrl.activity.lng}}" zoom="16">
<marker position="{{$ctrl.activity.lat}}, {{$ctrl.activity.lng}}"></marker>
</ng-map>
</div>
My question is:
How to replace my markers by circles?
Thanks a lot !
You can add "Circles" to your map as described in the official API documentation.
https://developers.google.com/maps/documentation/javascript/examples/circle-simple
Important is this part:
var cityCircle = new google.maps.Circle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,
center: citymap[city].center,
radius: Math.sqrt(citymap[city].population) * 100
});
It's pretty straight forward.
Instead of citymap[city].center you need to pass your lat/lang object, for example {lat: 41.878, lng: -87.629}.
For the radius you can pass any number value. In the maps demo they used the population.
For NG-Map:
<shape name="circle" ng-repeat="circle in vm.circles" no-watcher="true"
stroke-color="#FF0000"
stroke-opacity="0.8"
stroke-weight="2"
fill-color="#FF0000"
fill-opacity="0.35"
center="{{circle.position}}"
radius="{{circle.radius}}">
</shape>

Best method to label polygon in leaflet?

I am labeling 6 polygons in a GeoJson file. I am using the circleMarker on the each polygon centroid then calling .bindLabel, but I get this error: "circleMarker.bindLabel is not a function". Leaflet.label.js is called.
The map.
Code for GeoJSON:
var districts = L.geoJson(null, {
style: function (feature) {
return {
weight: 1,
opacity: 1,
color: 'blueviolet',
fillColor: 'plum',
fillOpacity: 0.5
};
},
onEachFeature: function (feature, layer) {
layer.on('mouseover', function () {
this.setStyle({
'fillColor': '#0000ff'
});
});
layer.on('mouseout', function () {
this.setStyle({
'fillColor': 'plum'
});
});
layer.on('click', function () {
window.location = feature.properties.URL;
});
var circleMarker = L.circleMarker(layer.getBounds().getCenter());
// e.g. using Leaflet.label plugin
circleMarker.bindLabel(feature.properties['NAME'], { noHide: true })
.circleMarker.addTo(map);
}
});
$.getJSON("data/districts.geojson", function (data) {
districts.addData(data);
});
You're calling a circleMarker method on your circleMarker object instance. That will never work. L.CircleMarker doesn't have a circleMarker method. This won't work:
circleMarker.bindLabel(feature.properties['NAME'], { noHide: true }).circleMarker.addTo(map);
This will:
circleMarker.bindLabel(feature.properties['NAME'], { noHide: true }).addTo(map);
And this will too:
circleMarker.bindLabel(feature.properties['NAME'], { noHide: true });
circleMarker.addTo(map);
But if you want to add a label without using L.CircleMarker you can simply do:
onEachFeature: function (feature, layer) {
layer.bindLabel(feature.properties['NAME'], { 'noHide': true });
}
You're also loading your scripts in the incorrect order:
<script src="assets/leaflet-label/leaflet.label.js"></script>
<script src="assets/leaflet-0.7.2/leaflet.js"></script>
Leaflet.label wants to extend classes from Leaflet, but it can't because Leaflet itself isn't loaded yet. So yes, you've loaded Leaflet.label, just not at the correct time. You could see this in your console, because Leaflet.label should throw an error when it doesn't find Leaflet. The correct way:
<script src="assets/leaflet-0.7.2/leaflet.js"></script>
<script src="assets/leaflet-label/leaflet.label.js"></script>

Polygon labels with Leaflet

Using leaflet 7.3 and polygon data in GeoJSON, how can I add labels from field: NAME?
Here is example of current GeoJSON polygon data. I would like to enable fixed labels in center of polygon, overlap OK.
var districts = L.geoJson(null, {
style: function (feature) {
return {
color: "green",
fill: true,
opacity: 0.8
};
},
onEachFeature(feature, layer) {
layer.on('mouseover', function () {
this.setStyle({
'fillColor': '#0000ff'
});
});
layer.on('mouseout', function () {
this.setStyle({
'fillColor': '#ff0000'
});
});
layer.on('click', function () {
window.location = feature.properties.URL;
});
}
});
$.getJSON("data/districts.geojson", function (data) {
districts.addData(data);
});
In onEachFeature callback, you can get the center of the L.Polygon created by GeoJSON layer and bind a label to it.
var polygonCenter = layer.getBounds().getCenter();
// e.g. using Leaflet.label plugin
L.marker(polygonCenter)
.bindLabel(feature.properties['NAME'], { noHide: true })
.addTo(map);
Here is an example: http://jsfiddle.net/FranceImage/ro54bqbz/ using Leaflet.label

Gmap3 Clear Directions

I need to recalculate the directions, when another marker is clicked or when my origin marker is dragged to another location.
at the moment, I am inserting a marker when a user inserts his/her address then when the users clicks on any existing marker it calculates the directions. Unfortunately it doesn't clear the previous directions.
Any Help at all will be greatly appreciated.
Here's the code:
jQuery(document).ready(function() {
jQuery.getJSON('./index.php', {
option: "com_locate",
view: "branches",
tmpl: "component",
format: "json",
},
function(json){
jQuery(function(){
jQuery("#googleMap").gmap3({
map:{
options: {
center:[-29.8191,25.3499],
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
streetViewControl: false
}
},
marker: {
values: json,
options: {
icon: new google.maps.MarkerImage("http://maps.gstatic.com/mapfiles/icon_green.png")
},
events:{
mouseover: function(marker, event, context){
jQuery(this).gmap3(
{clear:"overlay"},
{
overlay:{
id: "tooltip",
latLng: marker.getPosition(),
options:{
content: "<div class='infobulle"+(context.data.drive ? " drive" : "")+"'>" +
"<div class='bg'></div>" +
"<div class='text'>" + context.data.city + " (" + context.data.telephone + ")</div>" +
"</div>" +
"<div class='arrow'></div>",
offset: {
x:-46,
y:-73
}
}
}
});
},
mouseout: function(){
jQuery(this).gmap3({clear:"overlay"});
},
click: function(marker, event, context){
markerSelected(context.id);
}
}
}
});
///////////////
jQuery('#test-ok').click(function(){
var addr = jQuery('#test-address').val();
if ( !addr || !addr.length ) return;
jQuery("#googleMap").gmap3({
getlatlng:{
address: addr,
callback: function(results){
if ( !results ) return;
jQuery("#googleMap").gmap3({
clear:{id:"user"}
},
{
marker:{
latLng:results[0].geometry.location,
id:"user",
name:"user",
options:{
draggable: true
}
},
map:{
center: true,
zoom: 5
}
});
}
}
});
});
jQuery('#test-address').keypress(function(e){
if (e.keyCode == 13){
jQuery('#test-ok').click();
}
});
///////////////
///////////////
function markerSelected(id){
var marker = jQuery('#googleMap').gmap3({get:id});
var usermarker = jQuery('#googleMap').gmap3({get:"user"});
jQuery("#googleMap").gmap3({
getroute:{
options:{
origin:[usermarker.getPosition().lat(),usermarker.getPosition().lng()],
destination:[marker.getPosition().lat(),marker.getPosition().lng()],
travelMode: google.maps.DirectionsTravelMode.DRIVING
},
callback: function(results){
if (!results) return;
jQuery(this).gmap3({
map:{
options:{
}
},
directionsrenderer:{
container: jQuery(document.createElement("div")).addClass("googlemap").insertAfter(jQuery("#googleMap")),
options:{
directions:results
}
}
});
}
}
});
}
});
});
});
The code you're using creates a new DOM element each time you do a directions request, without removing any existing such elements or replacing content in any existing elements. The pertinent part of your code is this:
directionsrenderer:{
container: jQuery(document.createElement("div")).addClass("googlemap").insertAfter(jQuery("#googleMap")),
// The above creates a new DOM element every time markerSelected() is called!
options:{
directions:results
}
}
You want to create that only once. If you want, you can do it directly in the HTML markup.
Use the below as a replacement for your getroute callback function. I've plugged in a unique ID for the container element and left the "googlemap" class intact in case it's needed for CSS or other sections of code. Since you specifically want only one set of directions to be visible, though, let's select your container by ID.
callback: function(results){
if (!results) return;
if (!jQuery("#dircontainer").length>0) {
jQuery("<div id='dircontainer' class='googlemap'></div>").insertAfter("#googleMap");
} // Creates your directions container if it doesn't already exist.
else {
jQuery("#dircontainer").html("");
} /* I'm clearing the existing contents of the container in case gmap3 doesn't
automatically clear it when the new directions are inserted.
You can experiment with removing this else statement. */
jQuery(this).gmap3({
map:{
options:{
}
},
directionsrenderer:{
container: jQuery("#dircontainer"),
options:{
directions:results
}
}
});
}
I'm making some assumptions here about the way the gmap3 plugin works; I've worked with jQuery and the Google Maps JS API, but not with this plugin.

Categories