Unable to hide marker from GMap v3 - javascript

I can have a bunch of locations with different categories to show on the map. Eventually I'd like to apply a filter on them. Probably the scenario is very familiar as I found many of them on the web while I was trying to solve my issue. I put the markers on my map and I can find no way to hide them. Here is how I try it:
function addLocations($content, id, map){
var $mapdiv = $content.find('div.map_div');
catValues = [map.catPrimary, map.catWhite, map.catGreen, map.catYellow, map.catRed, map.catBrown, map.catPurple, map.catGray, map.catOrange];
db.locations.all(function(obj){
$.each(obj, function(index, location){
if(location.value.nodeID == id){
var latitude = location.value.latitude;
var longitude = location.value.longitude;
var description = location.value.description;
var category = location.value.category;
var position = new google.maps.LatLng(latitude, longitude);
if(category == "0"){
homeLocation = position;
$mapdiv.gmap('get','map').setOptions({'center':position});
}
var marker = new google.maps.Marker({
position: position,
icon: "assets/img/marker_" + category + ".png",
category: category,
shadow: iconShadow,
});
marker.setMap( $mapdiv.gmap('get','map') );
$mapdiv.gmap('addMarker', marker).click(function() {
$mapdiv.gmap('openInfoWindow', { 'content': description + "<br/> (" + catValues[category] + ")"}, this);
});
}
});
markers = $mapdiv.gmap('get', 'markers');
for(var i = 0; i<markers.length; i++){
if(markers[i].category != "0"){
//"not primary, hiding
markers[i].setVisibile(false);
}
}
});
All the markers are shown and the ones that are supposed to be hidden are not. I also tried adding the markers to an array before I add them to the map and work with them, but no success. When I include the markers[i].setVisible(false) around a try and catch it says "Object # has no method 'setVisible'. Surprisingly if I test markers[i].getVisible() I get the value true.
I appreciate your help in advance.

I believe the correct code is markers[i].setMap(null);
https://developers.google.com/maps/documentation/javascript/overlays#RemovingOverlays
From the article:
Removing Overlays
To remove an overlay from a map, call the overlay's setMap() method, passing null. Note that calling this method does not delete the overlay; it simply removes the overlay from the map. If instead you wish to delete the overlay, you should remove it from the map, and then set the overlay itself to null.
If you wish to manage a set of overlays, you should create an array to hold the overlays. Using this array, you can then call setMap() on each overlay in the array when you need to remove them. (Note that unlike in V2, no clearOverlays() method exists; you are responsible for keeping track of your overlays and removing them from the map when not needed.) You can delete the overlays by removing them from the map and then setting the array's length to 0, which removes all references to the overlays.

Related

Hide markers from google maps when click an external link and only show its corresponding marker

How do i change my center for google maps with a link and remove other markers? i have this code
https://jsfiddle.net/m9ugbc7h/
So, i need to create a link for example
Ventura
In this case the function must change google maps center to focus the "ventura" marker and hide the other markes and when the user clicks on
Dolphinaris
the zoom will change and will hide every other marker and show only the ones of Dolphinaris
Thanks in advance
Make map visible outside of jQuery(document).ready.
Create var markers = []; array.
When crating markers, add custom property name to it, and push marker into markers array:
var marker = new google.maps.Marker({
position: new google.maps.LatLng(21.0241839, -86.8148164),
map: map,
visible: true,
icon: ventura,
name: 'ventura',
});
markers.push(marker);
On click, invoke resetMap() function:
Ventura
Inside resetMap function, set center and zoom to map, iterate markers, matching them by custom property name - matched one set visible, others set to invisible.
function resetMap(lat, lon, zoom, name) {
var newPos = new google.maps.LatLng(lat, lon);
map.setCenter(newPos);
map.setZoom(zoom);
markers.forEach(function(marker) {
if(marker.get('name') == name)
{
console.log('match');
marker.setVisible(true);
}
else
{
marker.setVisible(false);
}
});
Working fiddle: https://jsfiddle.net/m9ugbc7h/1/
EDIT:
Question: "is there any way to change smoothly the zoom and coordinates?"
Yes, use method:
panTo(latLng:LatLng|LatLngLiteral)
Changes the center of the map to the given LatLng. If the change is
less than both the width and height of the map, the transition will be
smoothly animated.
https://developers.google.com/maps/documentation/javascript/reference?csw=1
EDIT 2:
Implementing panTo is easy:
map.panTo(newPos);
instead of:
map.centerTo(newPos);
but as I have faced a bit 'flickering' effect due to hide/show markers that are close on the map, I have added some delay in functions invocation + markers show/hide:
function resetMap(lat, lon, zoom, name) {
var newPos = new google.maps.LatLng(lat, lon);
$.when( map.setZoom(zoom) ).done(function(){
$.when( map.panTo(newPos)).done(function(){
setMarkerVisibility(name);
});
});
}
And showing matched marker is now executed with 300 ms delay:
function setMarkerVisibility(name){
markers.forEach(function(marker) {
console.log(marker.get('name'));
if(marker.get('name') == name)
{
setTimeout(function(){ marker.setVisible(true); }, 300);
}
else
{
marker.setVisible(false);
}
});
}
It looks a bit smoother like this.
Working fiddle: https://jsfiddle.net/m9ugbc7h/3/

Add a filter to markers that have been queried from a fusion table and then clustered with markerClusterer

I'm getting my markers and then clustering them like this:
var query = "SELECT Latitude, Longitude, Icon, 'Nr.', Info, 'W/D/L' FROM " +
'11jvxEY_amSEUy4IaWZE4652trcb3VLUu_x4XMUeD';
var encodedQuery = encodeURIComponent(query);
// Construct the URL
var url = ['https://www.googleapis.com/fusiontables/v1/query'];
url.push('?sql=' + encodedQuery);
url.push('&key=AIzaSyAT76tcYefMoGlGrAgBhFFF22W8JhQyQBI');
url.push('&callback=?');
//example URL
//https://www.googleapis.com/fusiontables/v1/query?sql=SELECT longitude_latitude FROM 1WukvEi1lbr-5Eo0Xn-Vqi5OKS7jhvt1aPmDdOD8I LIMIT 5&key=AIzaSyAT76tcYefMoGlGrAgBhFFF22W8JhQyQBI
// Send the JSONP request using jQuery
$.ajax({
url: url.join(''),
dataType: 'jsonp',
success: function (data) {
var rows = data['rows'];
var markers = [];
for (var i in rows) {
//insert info window code
var infoWindow = new google.maps.InfoWindow();
var lat = rows[i][0]
var lng = rows[i][2]
var image = rows[i][3]
var title = rows[i][3]
var content = rows[i][4]
var result = rows[i][5]
var coordinate = new google.maps.LatLng(lat,lng);
var marker = new google.maps.Marker({'position': coordinate,
'icon': image,
'title': 'Länderspiel #'+title,
'result': result
});
google.maps.event.addListener(marker, 'mouseover', (function(marker, content) {
return function(){
infoWindow.setContent(content);
infoWindow.open(map, marker);
}
})(marker, content));
google.maps.event.addListener(marker, 'mouseout', function() {
infoWindow.close();
});
markers.push(marker);
}
// function filter() {
// var where = generateWhere();
//
// if (where) {
// if (!marker.getMap()) {
// marker.setMap;
// }
// marker.setOptions
var markerCluster = new MarkerClusterer(map, markers);
}
});
I've begun to add a filter (commented out), trying to copy this method, but I'm not sure if that will work. I found another example, that seems to be doing exactly what I want, here, but I can't see, where they get the marker-properties they use to filter them from... I'd like to create a variable from the same query that assigns the markers different icons, getting info from the 'W/D/L' column (already included in the code), and then filter the markers by whether that information returns 'W', 'D', or 'L' (win, draw, or loss). I'm a noob, so can someone walk me through it?
The conditions you may retrieve in any desired way, when the user should be able to define the conditions a checkbox should be appropriate, so create checkboxes with the desired values W,D and L.
Observe the click-event of the checkboxes and create the where-clause based on the values of the checked boxes. With jQuery it may look like this:
var where=[];
//ancestor is the common ancestor of all the checkboxes
$('input:checked',ancestor).each(function(){where.push(this.value)});
the result so far will be an array containing the values of the checked checkboxes, e.g. ['W','L'] .
This array now may be used to create the where-clause. The where-clause for the example-array should be :
where 'W/D/L' IN('W','L')
it may be created via:
" where 'W/D/L' IN('"+where.join("','")+"')"
append this where-clause to query and the results will be filtered.
Demo: http://jsfiddle.net/doktormolle/xd8Qp/
This is an addition to the answer provided by #DrMolle.
I tried to copy #DrMolle's demo, but the map initially did not render the markers as well.
It worked after including the necessary script sources which were missing:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>

how to pass data with marker in leaflet js

I am using leaflet js with openstreetmap in my project.
I have multiple circlemarkers at same place in my map.
I want to store some Id in that circlemarkers so that I can Identify that which data should be refereed when circlemarker is clicked.
My circlemarker is
var myMarker = L.circleMarker(myPoint, { title: 'unselected', radius: 20 });
myMarker.addTo(map);
Here I am using title for other purpose that's why I cant use it.
Can any one tell me some way to do this.
It sounds like you would like to add new functionality (functions, properties, etc) to an existing class. It would make sense to use object-oriented principals for this. For this purpose, I'd recommend you extending the CircleMarker class to add those properties.
customCircleMarker = L.CircleMarker.extend({
options: {
someCustomProperty: 'Custom data!',
anotherCustomProperty: 'More data!'
}
});
Now when you create your circle marker, create an instance of your extended object instead.
var myMarker = new customCircleMarker(myPoint, {
title: 'unselected',
radius: 20,
someCustomProperty: 'Adding custom data to this marker!',
anotherCustomProperty: 'More custom data to this marker!'
});
myMarker.addTo(map);
Now you can get the properties like you would any other option from the marker. This is just a simple case of extending, and you can do more as needed, such as adding other properties or functions to the object.
JSFiddle example: JSFiddle
With the current version of leaflet (0.8-dev) you can just set your custom properties on the marker object itself, without having to create a custom marker class...
function map() {
return L.map('leaflet-canvas',
{
maxZoom: 10,
minZoom: 0,
crs: L.CRS.Simple
});
}
var map = map().setView([0, 0], 10).on('click', onMapClick);
function onMapClick(e) {
var marker = L.circleMarker(e.latlng, {draggable:true});
marker.myCustomID = Math.floor((Math.random() * 100) + 1);
marker.on('click', onMarkerClick);
map.addLayer(marker);
// 'click' the new marker to show the ID when marker created
marker.fireEvent('click');
}
function onMarkerClick(e) {
alert(e.target.myCustomID);
}
Here is a TypeScript friendly way:
DataMarker.ts
import * as L from 'leaflet';
export class DataMarker extends L.Marker {
data: any;
constructor(latLng: L.LatLngExpression, data: any, options?: L.MarkerOptions) {
super(latLng, options);
this.setData(data);
}
getData() {
return this.data;
}
setData(data: any) {
this.data = data;
}
}
SomeOtherFile.ts
import { DataMarker } from './DataMarker';
const marker = new DataMarker([ lat, lng ], anyData, markerOptions);
--
Note 1: I decided not to merge the marker options with the data property
Note 2: Adjust the type of data if you need something more specific
marker is basically javascript object rite.
Below snippet solve my case simply.
var marker = new L.marker([13.0102, 80.2157]).addTo(mymap).on('mouseover', onClick);
marker.key = "marker-1";
var marker2 =new L.marker([13.0101, 80.2157]).addTo(mymap).on('mouseover', onClick);
marker2.key = "marker-2";
function onClick(e) {
alert(this.key); // i can expect my keys here
}
just to complete the picture , to create a handler which will respond to a mouse click on a marker and provide access the new options
function onMarkerClick(e) {
console.log("You clicked the marker " + e.target.options.someCustomProperty);
console.log("You clicked the marker " + e.target.options.anotherCustomProperty);
}
marker.on('click', onMarkerClick);
Try this Uniquely identifying Leaflet Markers , its working for me.
//Handle marker click
var onMarkerClick = function(e){
alert("You clicked on marker with customId: " +this.options.myCustomId);
}
//Create marker with custom attribute
var marker = L.marker([36.83711,-2.464459], {myCustomId: "abc123"});
marker.on('click', onMarkerClick);
I would recommend to structure in your data for your markers in the standard GeoJSON format, which makes it compatible for direct saving as shapefile, etc.
var myMarker = L.circleMarker(myPoint, { title: 'unselected', radius: 20 });
myMarker.properties.id = your_Id;
myMarker.addTo(map);
To retrieve the stored information and do things with it or pass it on to other parts of your program, showing a sample onclick function:
myMarker.on('click',markerOnClick);
function markerOnClick(e) {
my_ID = e.layer.properties.id;
console.log(my_ID, e.latlng);
// do whatever you want with my_ID
}
It took me a while to find out the e.layer.properties way to access the clicked marker's properties, so hope this helps someone. Most other examples only focused on yielding the lat-long of the marker, e.latlng.
Note that you can use this same code even with a whole layer / group of markers. The function will work on each individual marker.
I have a easy solution. options property in each circleMarker is the good place to store custom value.
var myMarker = L.circleMarker(myPoint, { custom_id: 'gisman', radius: 20 });
myMarker.addTo(map);
You can easily retrive the value in options.
function markerOnClick(e) {
var id = e.options.custom_id;
}

With OpenLayers, what is the correct way of removing a markers layer, and the popups?

LoadPin is a function to add a marker to a map. It initializes the layer on the first call. map is an openlayers map object.
But using map.removeLayer("markers") or "Markers", does not remove the markers from the map. I saw a mention of a destroy operation to do this but cant find that.
AND, how do I remove the popups?
var markers = null
function LoadPin(LL, name, description) {
var size = new OpenLayers.Size(36, 47);
var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h);
var icon = new OpenLayers.Icon('http://www.waze.co.il/images/home.png', size, offset);
if (markers == null) {
markers = new OpenLayers.Layer.Markers("Markers");
map.addLayer(markers);
}
var marker = new OpenLayers.Marker(LL, icon)
markers.addMarker(marker);
var bounds = markers.getDataExtent();
map.zoomToExtent(bounds);
map.addPopup(new OpenLayers.Popup.FramedCloud("test", LL, null,
"<div style='font-family:Arial,sans-serif;font-size:0.8em;'>" + name + "<br>" + description + "</div>",
anchor = null, true, null));
}
You can remove individual markers from a marker layer with:
markers.removeMarker(marker);
Removing the entire layer, with markers should be achieved with:
markers.destroy();
You should be able to remove a popup with:
map.removePopup(popup);
where popup is the Popup object created earlier.
I know this post is old but to remove all markers from the marker layer list use:
markerLayer.clearMarkers();
Try the any of below code i hope it will help you.
this.markerSource.removeFeature(this.iconFeature);
or
this.markerSource.removeFeature(iconFeature);

Google Maps: remember id of marker with open info window

I have a Google map that is showing a number of markers. When the user moves the map, the markers are redrawn for the new boundaries, using the code below:
GEvent.addListener(map, "moveend", function() {
var newBounds = map.getBounds();
for(var i = 0; i < places_json.places.length ; i++) {
// if marker is within the new bounds then do...
var latlng = new GLatLng(places_json.places[i].lat, places_json.places[i].lon);
var html = "blah";
var marker = createMarker(latlng, html);
map.addOverlay(marker);
}
});
My question is simple. If the user has clicked on a marker so that it is showing an open info window, currently when the boundaries are redrawn the info window is closed, because the marker is added again from scratch. How can I prevent this?
It is not ideal, because often the boundaries are redrawn when the user clicks on a marker and the map moves to display the info window - so the info window appears and then disappears again :)
I guess there are a couple of possible ways:
remember which marker has an open info window, and open it again when the markers are redrawn
don't actually re-add the marker with an open info window, just leave it there
However, both require the marker with an open window to have some kind of ID number, and I don't know that this is actually the case in the Google Maps API. Anyone?
----------UPDATE------------------
I've tried doing it by loading the markers into an initial array, as suggested. This loads OK, but the page crashes after the map is dragged.
<script type="text/javascript" src="{{ MEDIA_URL }}js/markerclusterer.js"></script>
<script type='text/javascript'>
function createMarker(point,html, hideMarker) {
//alert('createMarker');
var icon = new GIcon(G_DEFAULT_ICON);
icon.image = "http://chart.apis.google.com/chart?cht=mm&chs=24x32&chco=FFFFFF,008CFF,000000&ext=.png";
var tmpMarker = new GMarker(point, {icon: icon, hide: hideMarker});
GEvent.addListener(tmpMarker, "click", function() {
tmpMarker.openInfoWindowHtml(html);
});
return tmpMarker;
}
var map = new GMap2(document.getElementById("map_canvas"));
map.addControl(new GSmallMapControl());
var mapLatLng = new GLatLng({{ place.lat }}, {{ place.lon }});
map.setCenter(mapLatLng, 12);
map.addOverlay(new GMarker(mapLatLng));
// load initial markers from json array
var markers = [];
var initialBounds = map.getBounds();
for(var i = 0; i < places_json.places.length ; i++) {
var latlng = new GLatLng(places_json.places[i].lat, places_json.places[i].lon);
var html = "<strong><a href='/place/" + places_json.places[i].placesidx + "/" + places_json.places[i].area + "'>" + places_json.places[i].area + "</a></strong><br/>" + places_json.places[i].county;
var hideMarker = true;
if((initialBounds.getSouthWest().lat() < places_json.places[i].lat) && (places_json.places[i].lat < initialBounds.getNorthEast().lat()) && (initialBounds.getSouthWest().lng() < places_json.places[i].lon) && (places_json.places[i].lon < initialBounds.getNorthEast().lng()) && (places_json.places[i].placesidx != {{ place.placesidx }})) {
hideMarker = false;
}
var marker = createMarker(latlng, html, hideMarker);
markers.push(marker);
}
var markerCluster = new MarkerClusterer(map, markers, {maxZoom: 11});
</script>
You should probably create all your markers at an initial stage with your createMarker() method, and store the returned GMarker objects inside an array. Make sure to set the hide: true property in GMarkerOptions when you create your markers, so that they would be created as hidden by default.
Then instead of iterating through places_json.places, you could iterate through your new GMarker array. You would be able to get the coordinates of each marker with the GMarker.getLatLng() method, with which to check if each marker lies within the bounds.
Finally simply call GMarker.show() for markers that lie within the bounds, or GMarker.hide() to hide them.
You would eliminate the expensive destruction/creation of markers on each map movement. As a positive-side effect, this will also solve your GInfoWindow problem.
If you're using that many markers, make sure you use GMarkerManager. It's designed for many markers, with only a few visible at once.
http://mapki.com/wiki/Marker_Optimization_Tips

Categories

Resources