HTML5 Canvas Placemark for Google Maps API v3 - html

I'm looking for a way to generate complex Placemarks (or overlays that are "attached" to placemarks).
Is there a way (I haven't found it) with the Map v3 api to attach/overlay a on placemark?
Or, will I need to draw outside of the Google api and then have listener/s that trigger redrawing when the user pans the map?

You extend google.maps.OverlayView with an object that override onAdd(), draw(), and onRemove()
In onAdd you'll probably want to set up a reference to a pane in google.maps.MapPanes to put your markup into. Then you'll have to handle the pan and zoom events. You do that like so:
CustomOverlayView.prototype.initPanes = function() {
var panes = this.getPanes(); //object of type google.maps.MapPanes
this.drawPane = jQuery(panes.floatPane); //we will initialize our stuff in this div element
this.drawPane.attr("id", "map-draw-pane"); //conceivable to want to reference this, usefull for debugging
this.drawPane.css("background-color", "transparent"); //DONT COVER THE GOOGLE COPYRIGHT
};
In order for your canvas to be useful for drawing, you need a way to convert your google.maps.LatLng objects into Point objects with x and y variables. The answer is in google.maps.MapCanvasProjection which has various methods that compute location objects encoded as google.maps.LatLng objects into useful pixel coordinates (and back again).
var projection = this.getProjection();//google.maps.MapCanvasProjection
var drawingLocationPoint = projection.fromLatLngToContainerPixel(markerData.location);
Some details of how to put a canvas in google maps here: http://www.samedwards.net

This is easily done, so I'm sorry an answer didn't appear sooner. Hopefully this is still useful to you.
See:
http://code.google.com/apis/maps/documentation/javascript/overlays.html#CustomOverlays
And here's an example:
http://code.google.com/apis/maps/documentation/javascript/examples/overlay-simple.html
You need to implement a Javascript class which extends OverlayView. Specifically, you will write a draw() method that the Maps API will call whenever the state of the map has been changed (e.g. it has been dragged or zoomed).
In that method you can create a HTML5 canvas (or anything really) and draw whatever you need. You get access to the underlying map projection, which lets you reliably convert LatLngs to pixels for the current zoom level and projection type.

I would recommend looking at this semi official extension library for creating a canvas overlay:
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/canvaslayer/
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/canvaslayer/examples/hello2d.html
as well as this sample, which uses raphael instead, but shows how you might associate your additional objects with markers:
http://gmaps-samples-v3.googlecode.com/svn/trunk/cloud/cloud.html

Related

Google Maps: How to draw labels (country, city names, etc.) over my overlay

I need to draw some graphics over google maps. Graphics is not always transparent, so I'd like to draw text labels (country names, city names, etc.) over my graphics.
For graphics I use overlay map type , it is shown over base map. But I failed to draw labels over it?
I guessed that there shall be a way to draw base map twice, with different style settings (so I style map with not labels, put my overlay, and then put overlay with roadmap with labels only), but it does not seem like I can use basic map types as overlay ones. Another way I see is to manually get tile with labels only by composing URL. This works, but as far as I understand accessing map tiles directly is prohibited by ToS.
Is there a working and, well, legal way to do that?
Here is jsfiddle which illustrates URL composing solution: https://jsfiddle.net/GRaAL/jyr81p2c/
// here is how I get google maps tile with labels only
function getLabelsOnlyTile(coord, zoom) {
return "https://maps.googleapis.com/maps/vt?pb=!1m5!1m4!1i" + zoom + "!2i" + (coord.x) + "!3i" + (coord.y) + "!4i512!2m3!1e0!2sm!3i353022921!3m14!2sen!3sUS!5e18!12m1!1e47!12m3!1e37!2m1!1ssmartmaps!12m4!1e26!2m2!1sstyles!2zcC52Om9mZixzLmU6bHxwLnY6b24!4e0";
}
I found that StyledMapType could be used as overlay map type (have same interfaces), so I created StyledMapType with labels only and instead of registering it in map type registry just added it as overlay, this way:
var onlyLabels = new google.maps.StyledMapType([...], {name: 'labels'});
//draw useful data over map
map.overlayMapTypes.insertAt(0, new UsefulDataOverlay());
//and then draw labels over it
map.overlayMapTypes.insertAt(1, onlyLabels);
Full working example is here: https://jsfiddle.net/GRaAL/jyr81p2c/2/
You might want to check MapLabel for Google Maps V3:
This library allows text to be added to the map at a particular location. Note that the user's browser must support Canvas for the label to be displayed.
MapLabel class
This class extends OverlayView.
Note that browser <canvas> support is required for the label to be displayed. Analytics
Source:
https://github.com/googlemaps/js-map-label
How to add text label in Google Map API
Hope this helps

Change color of markers for each KML Layer?

I have many different KML layers on a Google Map (v3). Random colors of markers were assigned to each set of markers. I would like to be able to control this, however.
So far, this is what I have:
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
var kmlLayerOptions = { preserveViewport: true, suppressInfoWindows: true };
var Layer1 = new google.maps.KmlLayer('http://myurl.com/1.xml', kmlLayerOptions);
Layer1.setMap(map);
var Layer2 = new google.maps.KmlLayer('http://myurl.com/2.xml', kmlLayerOptions);
Layer2.setMap(map);
I need to be able to say I want Layer 1 to use blue markers and layer 2 to use red markers, but I can't seem to figure this out.
From what I can tell, there is no way to do this with the kmlLayerOptions, which is where it would seem like it would happen, so I don't see where else I could logically make this change other than directly on the layer object.
You can't change it with KmlLayer (at least currently, you could create an Enhancement request to add the functionality).
You can do it with FusionTablesLayers (import your KML into FusionTables, then use either the User Interface to set the icons or dynamic styling in the Google Maps API v3 (assuming you need less than 5 different icons, and the ones you want are available in FusionTables).
A final option would be to edit the existing KML to use the icons you want.
The KmlLayer renders according to the styling in the KML document itself, and you cannot override this in any layer options.
If you don't want to modify the KML itself, you could use a third party library such as http://code.google.com/p/geoxml3/ to render the KML on the clientside rather than having Google's servers render it, and this would give you the ability to override the rendering defaults.

google maps api v3: top and left pixel position of marker

I want to retrieve the top and left position of marker (in pixels) in google map api v3. How can this be done? I know that there are some hints on using fromLatLngToDivPixel(), but may I know how it works? example?
You mean the coordinates in pixels within the div? Look at http://qfox.nl/notes/116
overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
var point = overlay.getProjection().fromLatLngToContainerPixel(latLng);
or
var point = overlay.getProjection().fromLatLngToDivPixel(latLng);
Ugly indeed. Much easier in v2, where these methods were directly methods of GMap2 object. Another flaw of google api v3!
If you facing problem having the overlay undefined, that's because the object is created after the map is idle.
Better call this within event listener, full explanation here https://stackoverflow.com/a/6657723/4026345

Getting the bounds of a polyline in Google Maps API v3

Is there any easy ways to find the bounding box of a polyline using Google Maps API v3? I'm working on a project where I need to update the bounds as data is added and removed from the map. This is pretty easy by just doing bd.extend(point) where bd is the bound object and point is a LatLng object. The problem is when I start removing data I would like it to change the bounds and zoom back in. Are there any built in functions that can do this or will I need to write something for myself?
Expanding on oenpelli's solution, this is the extended getBounds() method that I am using to recreate the functionality from V2 API. This is working perfectly in my project.
google.maps.Polyline.prototype.getBounds = function() {
var bounds = new google.maps.LatLngBounds();
this.getPath().forEach(function(item, index) {
bounds.extend(new google.maps.LatLng(item.lat(), item.lng()));
});
return bounds;
};
Just remember that this needs to be added AFTER the API javascript is loaded, so in your init method.
The v2 API had the GPolyline.getBounds() method to do exactly this. However it appears that there is no equivalent method in the v3 API.
You may want to handle this by overriding the changed property of your Polyline MVCObject in order to be notified when the object changes state. Then you can calculate the bounding box using the LatLngBounds.extend() method that you suggested.
I think Google intentionally omitted such methods from the v3 API in an attempt to keep the API lightweight. A similar omission discussed a couple of days ago on Stack Overflow was the GMap2.clearOverlays() method.
You can also extend the Polyline class to add your own getBounds method. Refer to google maps api v3: add point on polyline beetwen two existing points on click polyline event for how to do this.

Marking streets in Google Maps

I want to create an overlay on top of Google Maps that displays different streets in different colors.
In the Google Maps API it is possible to create markers and polygons that cover certain areas.
Is there a way to somehow mark different streets?
It sounds to me like you are interested in showing some application specific coloring for your Google maps display (rather than traffic maps).
If so , then you should check out custom overlays. You can create your own transparent background overlay tiles (with your colored streets), match them up with the Google maps tiles and then overlay them on the map. You can find a description of this stuff in the Maps API reference - Overlays.
I have actually been interested in trying this out, and this question might be a good excuse. I'll let you know how I go.
Edit: Ok, I tried this and it was pretty straightforward. You just need to grab the tiles images when the google maps page load (for the area you would like to overlay). Make sure you keep track of the origional urls, because these have the x,y coordinates that you will need to write your tile overlay method.
Edit the tiles with your colored roads then upload them to your web server. Add the following code to use your overlay on the regular map:
var myCopyright = new GCopyrightCollection("© ");
myCopyright.addCopyright(new GCopyright('Demo',
new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180)),
0,'©2007 Google'));
// Create the tile layer overlay and
// implement the three abstract methods
var tilelayer = new GTileLayer(myCopyright);
// properties of the tile I based my tile on
// v=w2.97&hl=en&x=38598&s=&y=49259&z=17&s=Galil.png
tilelayer.getTileUrl = function(point, zoom) {
if (zoom == 17 && point.x == 38598 && point.y == 49259)
return "../pics/times_square.png";
};
tilelayer.isPng = function() { return true;};
tilelayer.getOpacity = function() { return 1.0; }
var myTileLayer = new GTileLayerOverlay(tilelayer);
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(40.75740, -73.98590), 17);
map.addOverlay(myTileLayer)
This code overlays my Thing eats NY tile:
at x = 38598 and y = 49259 at zoom level 17.
It is possible to create markers and polygons in the Google Maps API. You need to create GPolygon and/or GPolyline objects
Have a look to these tutorials
And if you want to obtain the coordinate (latitude, longitude) of certain streets, you may have a look to the source code of this page
I am not sure to fully understand your question: do you want to mark some given streets ?
in that case, a quick-and-dirty way could be to get the coordinates of all the addresses of the street and build a GPolygon according to them...
Have you concidered using OpenStreeMaps?
Try digging into the code used to show the traffic overlay on the normal Google Maps site.
Edit: I just looked at the code, and it appears that even Google decided it was easier to implement this by just generating the traffic lines on the server and pulling them down as transparent PNG overlays.
I just found this link, and I think this could interest you. It is a JavaScript package that provides functionality for displaying multiple routes on Google Maps.
Is it what you were looking for ??