The OverlayView approach is the way to do it. If it is not working then it could be because the map hasn't finished loading before you try to get the overlay projection.
Once you have created the map and the overlay, wait for the map idle event trigger and then attempt to use the overlay.
google.maps.event.addListenerOnce(map, 'idle', function() {
aPoint=overlay.getProjection().fromLatLngToDivPixel(labelA.getPoint());
bPoint=overlay.getProjection().fromLatLngToDivPixel(labelB.getPoint());
});
EDIT - Updated answer to reflect question changes
It's not a good idea to create the overlay and wait for the idle event every time you call the function. You should create the map and overlay once and continue the application once the map has loaded.
For Example
var map, overlay;
var labelLatLongSort = function(a, b) {
labelA = eval("label_"+a.deviceId);
labelB = eval("label_"+b.deviceId);
longOffset = eval("offsetOverlapWith_"+a.customId);
aPoint=overlay.getProjection().fromLatLngToDivPixel(labelA.getPoint());
bPoint=overlay.getProjection().fromLatLngToDivPixel(labelB.getPoint());
diffLat = bPoint.y-aPoint.y;
diffLong = aPoint.x-bPoint.x;
if (Math.abs(diffLong)>longOffset) return diffLong;
if (diffLat==0) {
return b.deviceId-a.deviceId;
}
return diffLat;
}
var init = function(callback) {
map = new google.maps.Map(div, options);
overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
google.maps.event.addListenerOnce(map, 'idle', function() {
callback();
});
}
var startApp = function() {
var diffLat = labelLatLongSort(a, b);
}
// start application on DOM load
init(startApp);
What I did here was put my application code inside a function called startApp
and pass this into the init
function as a callback. Once the init
function has loaded the map by waiting for the idle
event, it calls the callback function.
Depending on your application you may need to change the setup slightly.