I am trying to implement a custom overlay in the Google Maps API v3 using some custom drawing done with a canvas element. I basically play the Polygon element from the API, but with the ability to receive events from the user (the goal is to drop some things in this zone, with the drag'n removed naturally).
So the drawings work great, I attach the listener to the canvas element and that where problems arise. Safari (verified since 5.1.4) delivers an event until I draw a canvas element, extracting the context and adding the path. For Chrome (17), Firefox (10) and Opera (11) there are no problems.
Here you can view the page here . When you click on the gray polygon in the center of the map, add plop below the chart to verify that the event was delivered.
Here are some parts of the code, first creating an overlay and adding them to the panel.
EventReceiverOverlay.prototype.onAdd = function() { var holder = document.createElement('canvas'); holder.style.opacity = 0.5; this.canvas_ = holder; google.maps.event.addDomListener(holder, 'click', function(event) { document.getElementById('message_container').innerHTML += 'plop'; }, false); this.getPanes().overlayLayer.appendChild(holder); }
Then draw overlay (updateScreenPoints allows you to convert all the coordinates of the points to the coordinates of the pixels):
EventReceiverOverlay.prototype.draw = function() { var overlayProjection = this.getProjection(); var swCorner = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest()); var neCorner = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast()); this.updateScreenPoints(); var canvas = this.canvas_; if (canvas.getContext) { var ctx = canvas.getContext('2d'); ctx.save(); ctx.strokeStyle = '#f00'; ctx.lineWidth = 2; ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.style.width, canvas.style.height); canvas.style.position = 'relative'; canvas.style.left = Math.round(swCorner.x) + 'px'; canvas.style.top = Math.round(neCorner.y) + 'px'; ctx.beginPath(); ctx.moveTo(this.screenPoints_[0].x, this.screenPoints_[0].y); for (var i = 1; i < this.screenPoints_.length; i++) { ctx.lineTo(this.screenPoints_[i].x, this.screenPoints_[i].y); } ctx.fill(); ctx.restore(); } }
I tested various events (click, mouse, dragenter, etc.), different ways of attaching an event (via google.maps.event.addDOMListener , browser addEventListener and jQuery on ), with the same results: Safari refuses to play well, whereas others work as expected, calling my function.
I also tried adding an overlay to another display panel, such as overlayMouseTarget or floatPane, without any further changes.
To give another try, I applied a simple canvas (with the same shape, more or less the same drawing process) to check if Safari will receive an event in this case, and yes, it works.
Performing the same element with a simple div element works fine, the problem arises as soon as I start painting on canvas.
I'm not sure what I did wrong, or if there is an error between the Google Maps API and Safari. Therefore, your help will be greatly appreciated if you manage to go through the whole story that I just wrote :)
thanks
Edit Apparently, as Brendan Kenny reports, there are no problems with OS X 10.6.8 and Safari 5.1.2. I tested it with OS X 10.6.8 and Safari 5.0.5, and also no problem.
I made the second page here , without any changes except deleting the part of the drawing (I deleted all the parts that used the context from the canvas in the draw method). When you click on the red rectangle in the div below, "plop" is added, and it works as expected in Safari 5.1.4.
Edit 2 Fixed in Safari 6.0, I think I will not know what happened.