Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML/CSS Markers using Google Maps Javascript API v3

Our company just moved from Leaflet.js to the Google Maps API; I've search high and low trying to find a simple way of integrating HTML/CSS Markers/Boxes as overlays into the Google Maps Javascript API v3.

So far, i've found this tutorial: https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays

Nevertheless, I find it extremely clunky and I haven't been able to inject HTML/CSS code successfully into the map.

Does anybody know of an easier way of adding HTML/CSS Markers/Boxes unto Google Map?

I could go ahead and hack the map by assigning top/left coordinates to divisions and then attach them to the map with jQuery to markers on google map, but this is a workaround/hack and there must be a simple way of integrating these.

Thanks in advance!

like image 887
Antonio Rodriguez Martinez Avatar asked Jul 26 '12 22:07

Antonio Rodriguez Martinez


2 Answers

To save readers' time, I provide demo-purpose website here

For this question. Basically, to add HTML/CSS customized markers, I suggest implementing one subclass of OverlayView with the help of some external library.

  • First I need to clarify why you should inherit OverlayView class.
  • Second I need to demonstrate why an external library might help.

Okay. First, The google.maps.Marker class extends MVCObject. The OverlayView class also extends MVCObject. To make your HTML/CSS implemented customized marker behave normally and resemble one google.maps.Markerat behavioral and event-communication level (but not visual level), extending OverlayView class is one safe way, since constructing one instance of OverlayView will somehow "register" the instance itself to the internal map events management. I will explain how this "registration" happened below.

In order to extend OverlayView, you need to override three methods, onRemove() onAdd(), draw(). The purpose of overriding draw() is that, this method is intrinsically bound to several google map events, such as zoom_changed. The purpose of draw() is to redraw the dom element, make it appear at right position of map canvas, and have it correctly sized on map canvas. For example, one google.maps.Marker redraws itself every time when user zoom in or zoom out the map. Additionally, there are many different situations that will trigger draw() Similarly, onAdd() is invoked when tiles of map are ready, onRemove() is invoked when setMap() is invoked. There is a series of events being listened by these three methods. This is how "registration" happens in my point. This also explains why extending class OverlayView is one safe way to implement your HTML/CSS customized marker. Because you do not need to deal with map events listening yourself when you extending OverlayView. Otherwise, you have to.

Specifically to this question, "to implement one custom maker", you need to do things described above also.

On the "custom OverlayView example" given in your question. I can tell you what you need to change to make it behave like one marker.

In that example. the css left and top, and width is determined by pre-defined google.maps.Bounds, you should change this. You need code like following:

    CustomMarker.prototype.draw = function(){
      var overlayProjection = this.getProjection();
      // console.log("draw" + this.latLng);
      var anchor = overlayProjection.fromLatLngToDivPixel(this.latLng);

      if (this.dom_) {
        this.dom_.style.top = (Math.round(anchor.y- this.height_)).toString()+'px';
        this.dom_.style.left = Math.round( anchor.x - this.width_ / 2).toString() + 'px';
        $(this.dom_).outerWidth(this.width_); // I need to have this jQuery method 
      }

      // generally, the dom node left-top corner should not be generated at clicking poistion, but with offsets of both left and top
    };

Also you need to handle so called "dom events" by addDomListener() method provided by google maps API. Why they are "so-called" events?

Because, to make the HTML nodes attached to marker instances of the extended "OverlayView" class be able to respond to user behaviors (I am not calling browser events here) like "clicking" "double clicking", developer should append the nodes to pane `overlayMouseTarget".

The reason is that, actually above overlayMousetarget pane, there are several other non-zero width none-zero height map HTML nodes, which "shadowed" our custom marker node added to the DOM tree. So our marker CANNOT directly receive browser events like onclick, even if you have implemented the DOM event handler functions for it. They are "deaf".

So the purpose of appending our customized Marker to overlayMouseTarget pane(node) is that, Google Maps has its own mechanism for how to process received outmost browser events. Google map process them, and then notify those nodes appended to google map mangaged panes(those five nodes: floatPane mapPane markerLayer overlayLayer overlayMouseTarget)

Now you can understand why I am calling the "so-called" events when you invoking "addDomListener()". Because the original "click" browser event never reached our poor markers, instead, it responds to "click" action by listening to one internal google map event which is trigger by outmost original "click" browser event.

Now, lets focus one the second point: "I need to demonstrate why an external library might help" You have to handle different google map dom listeners to complete tasks originally you can do with several lines of CSS code.

For example, to realize pseudo class hover, you need to implement handler of mouseover mouseout and so on, do some CSS classes adding and removal.

With external library such mapcover.js, you can just set("mouseover": function cb() { /*your implementations here*/}).

Have written so much, I will just show one demo here: http://easysublease.org/mapcoverjs/

The detailed implementations how you can create your HTML markers can be found here

like image 175
Bowei Liu Avatar answered Oct 18 '22 10:10

Bowei Liu


You might want to check google.maps.InfoWindow (https://developers.google.com/maps/documentation/javascript/overlays#InfoWindows) and the google.maps.Marker (https://developers.google.com/maps/documentation/javascript/reference#Marker) of google maps. Any CSS you apply on the page will be applied to the InfoWindow as well.

like image 44
Silver Gonzales Avatar answered Oct 18 '22 11:10

Silver Gonzales