Google Maps API v3: MarkerWithLabel not showing until zoom - javascript

I'm converting an application that uses v2 of the google maps api to v3. As part of this I've had to upgrade the MarkerManager to the v3 version too.
I have a bit of an odd issue in that Markers are not showing until the user zooms the map, then they appear.
If I then zoom back to the original zoom level the markers remain, so it is not a min\max zoom issue. There are no errors reported in firebug\javascript console and if I put a breakpoint or console.log at the location where the marker is added, it's definitely being added.
The application is fairly large, so I can't put all the source here, but the code where the markers are added is as follows:
console.log("Adding Marker");
markerManager.addMarker(marker, 1, 19);
markerManager.refresh();
And the code where marker is created is similar to this:
var latLng = new google.maps.LatLng(y, x);
var marker = new MarkerWithLabel({
position: latLng,
title: "title",
labelClass: "marker",
labelContent: "Test",
icon: icon,
labelAnchor: new google.maps.Point(26, 32)
});
and icon is just a google.maps.MarkerImage. MarkerManager and MarkerWithLabel are documented here:
http://google-maps-utility-library-v3.googlecode.com/svn/tags/markermanager/1.0/docs/reference.html
http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerwithlabel/1.1.7/docs/reference.html
EDIT: I should add that before doing anything with the marker manager after creating it I have the following, so I'm not trying to add anything until it's loaded:
google.maps.event.addListenerOnce(markerManager, 'loaded', function () {
Anybody have any suggestions on where my mistake is likely to be?

I've found a fix for this, though I'm not really sure what other ramifications there might be to this. Basically in markermanager.js I replaced the following (~line 130)
google.maps.event.addListener(map, 'dragend', function () {
me.onMapMoveEnd_();
});
google.maps.event.addListener(map, 'zoom_changed', function () {
me.onMapMoveEnd_();
});
with this and the markers appear as expected. I'm still open to other ideas as I'd prefer not to be editing the markermanager file and I'm not sure of the performance (or other) impact of doing this
google.maps.event.addListener(map, 'idle', function () {
me.onMapMoveEnd_();
});
EDIT: Looking at the markermanager.js dev version, the have all 3 events in there. So it may just be worth using v1.1 if anybody else has this issue:
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markermanager/src/markermanager.js

Related

How to add markers to leaflet map with tabletop.js?

I'm using this quite nice guide to add markers from a Google sheet to a basic leaflet.js map:
https://rdrn.me/leaflet-maps-google-sheets/
The problem is, using these code snippets here i get all the data logged and returned in the console, but none of the points appear on the map itself.
This is probably some really basic JavaScript issue that i'm not able to see. Sorry, still learning.
Here's a jfiddle, linking to a demo sheets with one marker point
https://jsfiddle.net/xfs19cz7/1/
with the map part:
function init() {
Tabletop.init({
key: '*url to gsheets here*',
callback: myFunction,
simpleSheet: true
})
}
window.addEventListener('DOMContentLoaded', init)
function myFunction(data, tabletop) {
console.log(data);
}
var map = L.map('map-div').setView([64.6220498,25.5689638], 5);
var basemap = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Basemap (c) OpenStreetMap',
minZoom: 5,
maxZoom: 18
});
basemap.addTo(map);
function addPoints(data, tabletop) {
for (var row in data) {
var marker = L.marker([
data[row].Latitude,
data[row].Longitude
]).addTo(map);
marker.bindPopup('<strong>' + data[row].Info + '</strong>');
}
}
This should add one point to a basic map. Now actually the map is not at all rendered, and no marker shows up. I can't find any issues in the code making the map show up blank, but there probably are some.
The marker from gsheets is however logged in the console, i suspect there is something missing in my code relating to really basic javascript functions / looping / sloppy syntax.
Also tried the init() and addPoints(data, tabletop) parts to a map i had where the map with the same basemap link, which rendereded OK. Adding this still left the map rendering, but no markers showed up. Again, the gsheets was loaded as an array of objects.
Could anyone point me to this, probably very basic, issue in the code?
edit:
callback: myFunction,
line above needs to be changed to
callback: addPoints,
also, init function needs to be called and position set to absolute. Thanks for the working fiddle in answer marked as correct below.
Fixes
Try setting map position absolute
calling the init() function
Working fiddle

Infobox position always towards centre of map in Bing Maps

I am using Bing Maps v8 and I would like to get the Infobox to be a little smart on where it shows.
Here is a CodePen of what I have. If you hover over the pushpin, you'll notice that the infobox shows towards the top and is thus cut off from view.
function loadMapScenario() {
var map = new Microsoft.Maps.Map(document.getElementById('myMap'), {
credentials: 'Your Key Here',
center: new Microsoft.Maps.Location(51.50632, -0.12714)
});
var pinLocation = new Microsoft.Maps.Location(51.663088, -0.204133);
var pushpin = new Microsoft.Maps.Pushpin(pinLocation, null);
var infobox = new Microsoft.Maps.Infobox(pinLocation, { title: 'Map Center', description: 'London, UK', visible: false });
infobox.setMap(map);
Microsoft.Maps.Events.addHandler(pushpin, 'mouseover', function () { infobox.setOptions({ visible: true }) });
map.entities.push(pushpin);
}
Is there a way to make that smart, so that it always shows towards the centre of the map, this way it'll always be in view.
I have found this which moves the map about so that the infobox is within view, but that is not what I'm after. I don't want the map moving about, just the infobox to show towards the centre of the map.
There is a custom infobox module available that provides this exact functionality. It will reposition itself so that it is always in view. You can find this module here: http://bingmapsv7modules.codeplex.com/wikipage?title=Custom%20Infobox%20Control
It is supported in Bing Maps V7 and V8.

What would make a Google map Ag object returned without mapDataProvider?

I'm working on an SPA project (ionic, so it's angular with ui-router) where I need to display two different maps on two different pages/controllers.
The first map is a general map (let's call it the main map)where a few locations are marked and the second one (let's call it the edit map)is a focus on a specific location where the user can edit the location by dragging the marker.
The general implementation scheme I'm using is that I'm calling a initMap method from mappingService that instanciates a google map from each controller.
$rootScope.markers = [];
this.initMap = function initMap(mapTarget, mapCenter) {
// the initMap function initialize the map it takes two arguments:
// + mapTaget which defines the html element the map is bound to.
// + mapCenter that defines the center of the map and whether to display the center
var markup = "<div id='" + mapTarget.mapId + "'></div>";
document.getElementById(mapTarget.containerId).innerHTML = markup;
var centerPos = new google.maps.LatLng(mapCenter.lat, mapCenter.lng);
$rootScope.map = new google.maps.Map(document.getElementById(mapTarget.mapId), {
center: centerPos,
zoom: 18,
disableDefaultUI: true
});
// eventually place a person marker for the user's position
if (mapCenter.display) {
console.log('placing the position marker');
$rootScope.markers[0] = new google.maps.Marker({
position: {lat: mapCenter.lat, lng: mapCenter.lng},
map: $rootScope.map,
title: 'userLocation',
icon: './img/person_icon.png'
});
}
};
The only difference is that on the main map I'm first calling a geolocate service the return a promise and I'm using the returned location coordinates to then call the mapping service:
geolocateService.getLocalPosition()
.then(function(coords) {
mappingService.initMap(
{containerId: $scope.mapContainer, mapId: $scope.mapId},
{lat: coords.lat, lng: coords.lng, display: true}
);
While on the edit map I'm calling directly the mapping service.
mappingService.initMap(
{containerId: $scope.mapContainer, mapId: $scope.mapId},
{lat: $scope.location.lat, lng: $scope.location.lng, display: false}
);
I am able to render both maps without problem and even to add markers and some event listeners.
However, I run into the problem that after some sequence of actions, for example going from the main map to the edit map two times, one of the map would suddenly become blank (white to be exactly, so it doesn't seems to be something that I could solve by resizing the map). I'm receiving the Ag object and the only difference is that I don't get the mapDataProviders property on the broken map.
When it works, I get:
Ag object when it works
While when it doesn't, I get:
Ag object when it doesn't work
The code snippet above is my last implementation attempt. I've been trying to implement those maps from a lot of different ways to no avail. Among those attempts, I tried:
totally separates both instanciation, dividing the initMap methods into an initMainMap and an initEditMap.
using one instance for both maps and replacing the DOM element> This is what you see above with the following additional method that is called when leaving the view:
this.removeMap = function removeMap(containerId) {
var container = document.getElementById(containerId);
$rootScope.markers = [];
container.innerHTML = '';
// important part:
var old_element = container;
var new_element = old_element.cloneNode(true);
old_element.parentNode.replaceChild(new_element, old_element);
delete $rootScope.map;
}
knowing that on both views I have either:
or
<div id="edit-map-container"></div>
I'm trying to understand what would make the google map API return a map without mapDataProvider (which I believe means that the map works and even starts to render except that it lacks the tiles to display).
P.S. it looks like there is a memory leak, which is apparently a well known issue.
If anyone has the answer to this, I'm a bit lost right here!

Create a smart, interactive map like the ones used on the FourSquare site

First off, I'm trying to create something like this using Angular.js: https://foursquare.com/explore?mode=url&near=San%20Francisco%2C%20CA&q=comedy
In summary, here are the tools I've tried:
Mapbox.js
Leaflet.js
Angular-Leaflet directive
For each, I've attempted to create a directive that would manage a list of locations that is associated with a map displaying those locations such that, when the user hovers over a list item, a tooltip appears above the location's marker on the map, and when they hover atop the location's marker on the map, a tooltip appears above that marker. (If this isn't clear, just visit the link above.) Hyperlinks, image, etc. should be able to appear within the tooltip. None of the above seem to give me the map portion of this functionality straight out of the box. Also, in order to even get markers to appear on the map, I have to essentially break away from idiomatic Angular, since the markers are vector items that are generated via the Leaflet/Mapbox toolkit. Writing this code feels wrong. Yes, I'm able to see the marker, but I can't really associate them with anything in the DOM. I'm confused.
I'm just at a loss for how to create a smart, interactive map that is associated with other elements on my page. Libraries like Angular-leaflet allow you to get a map on your page pretty easily, but customization is PAINFUL (or so it seems). Is Angular.js, in combination with any of the above three tools, the way to go? Is there something I'm simply failing to understand?
in angular-leaflet-directive, you can bind marker events.
here is an example that implements the dragend event (taken from here). you should be able to use the mouseover event, get the hovered marker from the events arguments and show it's popup.
var app = angular.module("demoapp", ["leaflet-directive"]);
app.controller('MarkersSimpleController', [ '$scope', function($scope) {
var mainMarker = {
lat: 51,
lng: 0,
focus: true,
message: "Hey, drag me if you want",
draggable: true
};
angular.extend($scope, {
london: {
lat: 51.505,
lng: -0.09,
zoom: 8
},
markers: {
mainMarker: angular.copy(mainMarker)
},
position: {
lat: 51,
lng: 0
},
events: {
markers: [ 'dragend' ]
}
});
$scope.$on("leafletDirectiveMarker.dragend", function(event, args){
$scope.position.lat = args.model.lat;
$scope.position.lng = args.model.lng;
});
} ]);

Angular google Maps

Hi i am currently working on angular Google maps https://github.com/dylanfprice/angular-gm
i am facing difficulties in setting the bounds and map center
<gm-map gm-map-id="'infoWindows'" gm-center="options.map.center" gm-zoom="options.map.zoom" gm-bounds="bounds" gm-map-options="options.map" class="map">
<gm-markers gm-objects="clinics"
gm-get-lat-lng="{ lat: object.practice.latitude, lng: object.practice.longitude }"
gm-get-marker-options="{ title: object.practice.name }"
gm-on-click="clk = object; infoWindow.open(marker.getMap(), marker);">
</gm-markers>
</gm-map>
make sure your map is already loaded.
therefor it is highly recommended to use promises.
var gmapPromise = angulargmContainer.getMapPromise('<mapId>');
gmapPromise.then(function(gmap) {
$scope.myGoogleMap = gmap;
});
In your case would be 'infoWindows'.
as there is to less context in your question, i can't really give you an answer what is wrong with your particular code but i'll give you some snippet which is always useful:
$scope.updateGoogleMap = function(map, options) {
// triggers a resize of the map and sets the correct center position
// requires a google map object and a google maps mapOptions object
$timeout(function(){
google.maps.event.trigger(map, 'resize');
map.setOptions(options);
});
};
a Google Maps mapOption object looks like this:
{
center: new google.maps.LatLng(47.123, 10.123),
zoom: 3,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
as ng-hide/show lead to some google maps resize misbehaviour, you might wanna call this when toggling views.
**by the way, if your are using the gm-map-options tag with a valid google.maps.MapOptions, you don't need the the extra 'gm-bounds', 'gm-zoom' or 'gm-center' arguments

Categories

Resources