I want to animate (fadein, fadeout) a marker in my GoogleMaps application (Web).
How can i assign any css class to a marker?
Or how can i access the specific marker? Do they have selectors like :after or something?
If not, whats the easiest way of applying animations to them?
The DOMNode that contains the image used for the marker isn't available via the API.
Furthermore, by default the markers will not be single DOMNodes, they will be drawn via canvas.
But the Marker-Image may be accessible via CSS when you use a unique icon-URL for each Marker.
Sample(using jQuery):
<style type="text/css">
img[src^='http://www.google.com/mapfiles/marker.png?i=']{
opacity: 0.5
}
</style>
<script type="text/javascript">
function initialize() {
var index=0;
var mapOptions = {
zoom: 14,
center: new google.maps.LatLng(52.5498783, 13.425209099999961),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
marker=new google.maps.Marker({position:map.getCenter(),
map:map,optimized:false,
icon:'http://www.google.com/mapfiles/marker.png?i='+(index++)});
google.maps.event.addListener(marker,'mouseover',function(){
$('img[src="'+this.icon+'"]').stop().animate({opacity:1});
});
google.maps.event.addListener(marker,'mouseout',function(){
$('img[src="'+this.icon+'"]').stop().animate({opacity:.5});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
How ist works:
The sample uses a single image as Marker-Icon (http://www.google.com/mapfiles/marker.png)
via CSS we apply a opacity. You may notice that there is a i-parameter inside the URL. This parameter will be used to make the img-src unique.
I use a variable which will be incremented to get a unique img-src:
var index=0;
//a few lines later:
icon:'http://www.google.com/mapfiles/marker.png?i='+(index++)
Now you'll be able to select the <img/>-element used for the marker, e.g. onmouseover/onmouseout via a attribute-selector.
When you wan't to use vanilla javascript you may use document.querySelector to access the image.
Note: you must set the optimized-option of the marker to false (this will force the API to render the marker as a single element)
Demo: http://jsfiddle.net/doktormolle/nBsh4/
There is a trick that can work if you for example want to change the cursor for the marker
Add this:
google.maps.event.addListener(YOURMARKER,'mouseover',function(){$(".gm-style div").addClass("markerClass")});
google.maps.event.addListener(YOURMARKER,'mouseout',function(){$(".gm-style div").removeClass("markerClass")});
and
#YOUR-CANVAS .gm-style div {cursor: default !important;}
#YOUR-CANVAS .gm-style div.markerClass{cursor:pointer !important}
works like a charm
An easy way is, select the marker and add a class the that selection.But for that you have to give each marker a title. Any animation would not work except google ones.
$("div[title=\"" + name+ "\"]").addClass("aClass")
I hope this helps someone.
Related
I began to use Google Map API recently and I tried the hello world sample in my own webpage. The only difference of my code from the original one is I display the map element in javascript code like this:
function showMap () {
container = document.getElementById("id_container");
container.innerHTML = "<div id=\"map_canvas\"><\/div>";
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
}
And in the external css file, I defined the width and height by fixed values for #map_canvas.
But I didn't get the expected result. The map showed for about 1 second and became all white (see the image below). When I zoom the map, I can see it flashing. I have searched on Google but I didn't get any solution and I don't even know what the problem is. Has anyone encountered the same problem before?
After several days' trying, I know what's happening --
I set the background attribute of all divs to be white. Though I reset the background of the map div to be "none", it doesn't work. The only solution is to avoid any definitions that would possibly give it a not "none" background, like "div {background-color: white;}".
However, feel free to set the background color of its parent tags.
I am using markerCLusterer V3 on a db file from Filemaker to generate a (semi-live) map of current delivery locations, based off of addresses. Grabbing the lat/long from Google and populating those
fields is no problem. Generating the map via markerClusterer is no problem. I am even hosting the JS locally so that I can change the maxZoom variable to break the clusters apart above max zoom, so that I can see multiple markers. However, with the markers at exactly the same lat / long, I can only see the last one entered. I would like to integrate OverlappingMarkerSpiderfier into this JS so that after I zoom in past the maxZoom, the markers would "spider" apart to see the markers (as an example, multiple pieces of equipment being delivered to the same address). I can't find any info here on on the web of how to do this. It's either that simple and I'm missing it or it hasn't been done yet. Thanks in advance for any help!
I'm using:
MarkerClustererPlus-2.0.14 and
OverlappingMarkerSpiderfier-version-??
At first only the clustering works, clicking on a cluster, zooms in but 2 or more markers on the exact same point still stay a cluster even when zoomed in to the maximum. Unfortunately no spiderfier showed up :-(.
But than a noticed the setMaxZoom() method on markerClusterPlus. When setting this too your appropriate zoom level (15 for me) spiderfier takes over beyond the zoom level. It looks like markerClusters says it ain't my business anymore from here on it's up to spiderfier :-).
Setting the max zoom will fix the problem:
minClusterZoom = 14;
markerCluster.setMaxZoom(minClusterZoom);
but for viewing purposes you may want to create a clusterclick listener to prevent it from zooming in really close on a cluster of points at the same location (clicking a cluster set the bounds of the map to cover the points in the cluster; if all points are at the same location it will zoom in all the way, which tends to look bad):
google.maps.event.addListener(markerCluster, 'clusterclick', function(cluster) {
map.fitBounds(cluster.getBounds()); // Fit the bounds of the cluster clicked on
if( map.getZoom() > minClusterZoom+1 ) // If zoomed in past 15 (first level without clustering), zoom out to 15
map.setZoom(minClusterZoom+1);
});
Integrating Spiderfier JS into markerClusterer
Download the oms.min.js file from here
Download the markerClusterer.js and the image folder from here
In order to make both work together you only need to add a maxZoom to the clusterMarker object
new MarkerClusterer(map, clusterMarker, {imagePath: 'images/m', maxZoom: 15});
(Zoomlevel 0 is the complete earth, and 20 is pretty close to the ground). This means that if you zoom into the map further as zoom level 15 (for example if you click on a cluster) then the clusters are not shown anymore. If you now click on markers that are on the exact same location (or close to each other) Spiderfier JS will trigger.
It follows now a minimal working example. I made some comments in the code so I think its self-explanatory, but here are some things to mention:
Replace YOUR_API_KEY with your api key
Make sure to load oms.min.js after you loaded the google maps api
Example:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script src="https://maps.googleapis.com/maps/apijs?key=YOUR_API_KEY">
</script>
<script src="oms.min.js"></script>
<script src="markerclusterer.js"></script>
<script>
window.onload = function() {
// cluster marker
var clusterMarker = [];
var map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng( 50, 3),
zoom: 6,
mapTypeId: 'terrain'
});
// Create infowindow
var infoWindow = new google.maps.InfoWindow();
// Create OverlappingMarkerSpiderfier instsance
var oms = new OverlappingMarkerSpiderfier(map,
{markersWontMove: true, markersWontHide: true});
// This is necessary to make the Spiderfy work
oms.addListener('click', function(marker) {
infoWindow.setContent(marker.desc);
infoWindow.open(map, marker);
});
// Some sample data
var sampleData = [{lat:50, lng:3}, {lat:50, lng:3}, {lat:50, lng:7}];
for (var i = 0; i < sampleData.length; i ++) {
var point = sampleData[i];
var location = new google.maps.LatLng(point.lat, point.lng);
// create marker at location
var marker = new google.maps.Marker({
position: location,
map: map
});
// text to appear in window
marker.desc = "Number "+i;
// needed to make Spiderfy work
oms.addMarker(marker);
// needed to cluster marker
clusterMarker.push(marker);
}
new MarkerClusterer(map, clusterMarker, {imagePath: 'images/m', maxZoom: 15});
}
</script>
</head>
<body><div id="map" style='width:400px;height:400px;'></div></body></html>
Recommendation
If you are starting from scratch, I would recommend to use the JS Libary Leaflet. Because this library provides you with the LeafletMarkerCluster plugin which is basically markercluster with Spiderfier integrated, and a lot of other cool stuff.
Advantage:
Cluster look really nice
Leaflet really easy to use and looks pretty
You do not need to customize the code, because Spiderfier and markerCluster already integrated
Some fancy other stuff: Like showing the border on hover of a region where marker are spread.
You can freely choose your map-tiles-provider and are no longer restricted to google maps (possible providers here)
Downsites:
You may need to invest 30min to learn and use the Leaflet API instead of the Google API
If you want to use Google Map Tiles, then you need to use this plugin, because you are only allowed to use the Google Tiles when using the Google API. This plugin is a wrapper for the Google API.
Here is an example code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
<link rel="stylesheet" href="leaflet/dist/MarkerCluster.css" />
<link rel="stylesheet" href="leaflet/dist/MarkerCluster.Default.css" />
<script src="leaflet/dist/leaflet.markercluster-src.js"></script>
<script>
$(document).ready(function(){
var tiles = L.tileLayer(***);//Depending on your tile provider
var map = new L.Map('map', {center: latlng, zoom: 1, layers: [tiles]});
var markers = new L.MarkerClusterGroup({
removeOutsideVisibleBounds: true,
spiderfyDistanceMultiplier: 2,
maxClusterRadius: 20
});
var markersList = [];
var sampleData = [{lat:50, lng:3}, {lat:50, lng:3}, {lat:50, lng:7}];
for (var i = 0; i < sampleData.length; i ++) {
var point = sampleData[i];
var location = new L.LatLng(point.lat, point.lng);
// create marker at location
var m = new L.Marker(location);
m.bindPopup("Number" +i); //Text to appear in window
markersList.push(m);
markers.addLayer(m);
}
var bounds = markers.getBounds();
map.fitBounds(bounds)
map.addLayer(markers);
}
</head>
<body><div id="map" style='width:400px;height:400px;'></div></body></html>
I came across this post because I was looking for the exact same thing, but lucky for me I have made it work!
I honestly didn't do anything special, I followed the integration guide for MarkerClusterer, and then followed the integration guide for OverlappingMarkerSpiderfier and they work flawlessly together.
When I click/zoom in on a cluster of properties that are all at the same address, initially it just shows the "top" marker, but when I click it, they Spiderfy just like you'd want them too!
What specific result are you getting when you try to use the two scripts together?
var markerClusterer = new MarkerClusterer(map, myMarkers, {
maxZoom: 15,
zoomOnClick: false
});
//zoom 0 corresponds to a map of the Earth fully zoomed out, 20 is closeup
//markerCluster goes away after zoom
//turn off zoom on click or spiderfy won't work
This question already has answers here:
Google map only loading half of itself
(4 answers)
Closed 2 years ago.
I just added a googlemap to a website. I is placed as presented in the toturials in a map_canvas div, and this div is nested inside another div like:
now the problem is that the map tiles stayes in the topleft corner but not the map background like this http://screencast.com/t/jeUSKijjwE
what could be wrong?
This is usually a problem with showing, hiding, or resizing a map.
In google maps v3, I believe you can call google.maps.event.trigger(map, 'resize'); where map is the reference to your google maps object.
I suggest load map with some time delay after checking the div is visible or not which is going to hold the map . Worked for me
$(document).ready(function () {
$('.togglebtn').click(function () {
if(!$('#map_canvas').is(':visible')){
setTimeout(function(){initialize()}, 500);
}
});
});
//your function
function initialize() {
var mapOptions = {
zoom: 3,
center : new google.map.LatLng(31.510474,80.352287),
center: new google.maps.LatLng(44.510474, 50.352287),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var contentSC_PAK = "SoftCircles Pakistan";
.....
.....
and rest of your map code to initialize map
});
}
I had this problem and discovered that in my case the issue was that I was creating the map_canvas div with javascript innerHTML.
The map would display correctly the first time, but the second time I'd call it (different map though) it would display the same map (wrong map), and the third time I'd call another map it would display it only in the top left corner. It would be in the top corner for all the rest of the calls.
All I had to do was put the div in the original HTML, and it works perfectly from there on out.
Hope this helps someone!
You have to use autosizse option. I had same issue, and i solved it.
Here the code when you open a modal and inside it, call a locationpicker.
$scope.map_picker = function(){
$("#map_modal").modal('show');
$('.us2').locationpicker({
location: {latitude: 33.997215339647724, longitude: -81.02654766235355},
radius: 300,
inputBinding: {
latitudeInput: $('.us2-lat'),
longitudeInput: $('.us2-lon'),
radiusInput: $('#us2-radius'),
locationNameInput: $('#us2-address')
}
});
**$('#map_modal').on('shown.bs.modal', function () {
$('.us2').locationpicker('autosize');
});**
}
The main logic is just have to use this line:
$('.us2').locationpicker('autosize');
But it is important how and where you are calling this line.
I've been unable to get the basic Google maps example working on my site. I have the following div on my page:
<div id="map_canvas" style="width:100%; height:100%"></div>
And the following in the head of my document:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(-34.397, 150.644);
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}
jQuery(document).ready(initialize);
</script>
It appears that the elements are getting loaded into my DOM, but there is no visible map on the page.
As per Google Map not showing up, it appears that percentage sizes on the div (e.g. 100%) don't work properly. I had to explicitly specify a pixel height and width for the div.
Use 100% only if you want to show google map on the whole screen..!!
Here is a sample which used 100% width height
http://www.rizeworkshop.com/basic-google-map-v3/
You have jQuery enabled on your site? Otherwise, within your body-tag create a "onload=initialize();"-attribut so that the javascript will be executed.
As far as I know your inital-request needs an API key?
the code looks ok and it's similar to the examples from the documentation so it should be working properly.
Have you tried printing some information on the screen from the initialize function? Check if the latlng, myoptions and map variables are created correctly.
If they are, there's a problem with calling the initialize function...
I tested your code and iw works fine if i use <body onload="initialize()"> as da_didi suggested.
Do you have an import directive for jquery.js?
Is there a way of preventing a Google Maps (JS, v3) map being displayed from the get-go? I'm doing some pre-processing and would like to show my 'Loading' spinner until everything is good to go (more eloquently put, hide the map -- e.g. the container div – until all pre-processing is complete – at which point, show the map).
Hooking up the map's idle event doesn't help that much, since the map is already displayed when this event hits.
I know that the container div gets inline-styled by GMaps after loading, my first idea was to clear out the style attribute (whilst listening to the idle event), but it would be interesting to see if there is a way of creating the map and not displaying it until all pre-processing is done.
Maybe by using an argument to the new google.maps.Map constructor, or a MapOption ?
Any thoughts on this?
Thank you in advance!
Also remember to call:
google.maps.event.trigger(map, 'resize');
if you have changed the size of the <div>. A display:none <div> has no size.
Or you could just hide it like with css visablility or css opacity.
$("#GoogleMap").css({ opacity: 0, zoom: 0 });
initialize();
google.maps.event.addListener(map,"idle", function(){
$('#Loader').hide();
$("#GoogleMap").css({ opacity: 1, zoom: 1 });
});
This works for me. I'm using the JQuery library.
$(document).ready(function(){
$('#Checkbox').click(function(){
$('#googleMapDiv').toggle();
initialize(); // initialize the map
});
});
another way to show the hidden map when map is first time rendering the <div> is to set style: visibility.
When firstly hidden, use visibility = hidden; to show use visibility = visible
the reason is: visibility:hidden means that the contents of the element will be invisible, but the element stays in its original position and size.
this works fine for me, I use jquery tabs
setTimeout(function() {
google.maps.event.trigger(map, "resize");
map.setCenter(new google.maps.LatLng(default_lat, default_lng));
map.setZoom(default_map_zoom);
}, 2000);
om this link https://code.google.com/p/gmaps-api-issues/issues/detail?id=1448
This will work
google.maps.event.addListener(map, "idle", function ()
{
google.maps.event.trigger(map, 'resize');
});
better way:
gmap.redraw = function() {
gmOnLoad = true;
if(gmOnLoad) {
google.maps.event.trigger(gmap, "resize");
gmap.setCenter(gmlatlng);
gmOnLoad = false;
}
}
and in show click event:
$("#goo").click(function() {
if ($("#map_canvas").css("display") == "none") {
$("#YMapsID").toggle();
$("#map_canvas").toggle();
if (gmap != undefined) {
gmap.redraw();
}
}
});
depending on what you are doing another posibility could be to have multiple bools you set to true when each process is done.
For example:
if you have a geocode service running which you want to wait for, you could have a var called
GeoState
and in the result part of the geocoder set GeoState to true,
then have a timed function check if all the services have returned true, when they have, make the map visible.