4

Ich versuche, ein benutzerdefiniertes Overlay in Google Maps API v3 zu implementieren, wobei einige benutzerdefinierte Zeichnungen über ein Canvas-Element erstellt wurden. Im Grunde reproduciere ich das Polygon-Element aus der API, aber mit der Fähigkeit, Ereignisse vom Benutzer zu empfangen (das Ziel ist es, einige Dinge in der Zone fallen zu lassen, mit nativem Drag'n Drop).Google Maps API v3: Benutzerdefiniertes Overlay mit Leinwandzeichnung, die keine Ereignisse in Safari empfängt

Also Zeichnung funktioniert gut, ich füge einen Listener an das Canvas-Element und das ist, wo Probleme passiert. Safari (getestet mit 5.1.4) liefert das Ereignis, bis ich etwas auf dem Canvas-Element zeichne, indem ich den Kontext abrufe und einen Pfad hinzufüge. Für Chrome (17), Firefox (10) und Opera (11) keine Probleme.

Sie können die Seite here anzeigen. Wenn Sie auf das graue Polygon in der Mitte der Karte klicken, sollte unter der Karte eine plop hinzugefügt werden, um zu überprüfen, ob das Ereignis geliefert wurde.

Hier sind einige Teile des Codes, zuerst das Overlay erstellen und es zu den Scheiben hinzufügen.

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) { 
/*  holder.addEventListener('click', function(event) { */ 
    document.getElementById('message_container').innerHTML += 'plop'; 
    }, false); 

    this.getPanes().overlayLayer.appendChild(holder); 
} 

dann die Overlay-Zeichnung (updateScreenPoints erlaubt es, alle Koordinaten der Punkte zu konvertieren, um Pixelkoordinaten):

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(); 
    } 

} 

ich mit verschiedenen Ereignissen getestet (klicken, Mouseover, dragenter-, etc.), verschiedene Möglichkeiten, das Ereignis anzuhängen (durch google.maps.event.addDOMListener, Browser addEventListener, und jQuery on), mit den gleichen Ergebnissen: Safari lehnt es ab, gut zu spielen, während die anderen wie erwartet funktionieren und meine Funktion auslösen.

Ich habe auch versucht, die Überlagerung zu einem anderen Kartenbereich, wie dem overlayMouseTarget oder dem floatPane, ohne zusätzliche Änderungen hinzuzufügen.

Um einen weiteren Versuch zu geben, habe ich eine einfache Leinwand (mit der gleichen Form, mehr oder weniger den gleichen Zeichenprozess) implementiert, um zu testen, ob Safari das Ereignis in diesem Fall empfängt, und ja, es funktioniert.

Das gleiche mit einem einfachen div-Element funktioniert perfekt, das Problem passiert, sobald ich auf der Leinwand zu zeichnen beginnen.

Ich bin mir nicht sicher, was ich falsch gemacht habe oder ob es einen Fehler zwischen Google Maps API und Safari gibt. So wird Ihre Hilfe sehr zu schätzen, wenn man es schafft, durch die ganze Geschichte zu gehen, ich schrieb gerade :)

Dank

bearbeiten Offenbar als Brendan Kenny berichtet gibt es keine Probleme mit OS X 10.6.8 und Safari 5.1.2. Ich habe es mit OS X 10.6.8 und Safari 5.0.5 getestet, und auch keine Probleme.

Ich machte eine zweite Seite, here, mit anderen Änderungen als das Entfernen des Zeichnungsteils (ich löschte alle Teile, die den Kontext aus dem Canvas in der draw-Methode verwendeten). Wenn Sie auf das rote Rechteck klicken, wird dem darunter liegenden div ein "plop" hinzugefügt, der wie erwartet in Safari 5.1.4 funktioniert.

Bearbeiten 2 In Safari 6.0 behoben, rate ich nicht, was passiert ist.

+0

Um es klar zu stellen: Das erwartete Verhalten besteht darin, dass Klicks auf den Canvas, der das graue Polygon enthält, dem Div unter der Karte einen "Plop" hinzufügen sollten. Auf welchem ​​Betriebssystem laufen Sie? Unter OS X 10.6.8 (Ausführen von Safari 5.1.2) wird der Plop immer dann angezeigt, wenn ich auf die Zeichenfläche auf der Seite klicke und alle Reaktionen wie in Chrome angezeigt werden. –

+0

Genau, es sollte ein Plop im div unterhalb der Karte hinzugefügt werden, wenn man auf das graue Polygon klickt. Ich verwende OS X 10.7.3 mit Safari 5.1.4. Ich werde versuchen, auf älteren Versionen von Safari zu testen, wenn ich einen finden kann, und die Frage mit den Ergebnissen aktualisieren. – vicould

Antwort

1

Google wirklich mag diese Technik nicht.Ihre Leinwand und Ihre Leinwand werden um den Z-Index kämpfen, nur einer wird das Mausereignis erhalten, und entweder A) wird Ihre Arbeit funktionieren, aber Sie können nicht auf die Karte klicken/schwenken/zoomen oder B) umgekehrt. Sie können es manchmal zum Laufen bringen, aber nach dem Schwenken der Karte wird es nicht funktionieren, weil die neuen Kacheln mit einem höheren Z-Index kommen. Wenn Sie die Steuerelemente von Google hinzufügen oder versuchen, das Zoomen mit zwei Fingern zu verwenden, sehen Sie, dass diese nicht funktionieren.

Verwenden Sie Googles Polygon-Klasse usw. und alle sollten mit der Welt übereinstimmen. Ich spreche aus Erfahrung - ich habe versucht, mein Projekt auf diese Weise zu machen und die gleiche Wand zu treffen. Ich habe mich nach Googles Willen gebeugt und alles ist groovig.

+0

Ich bin mir nicht ganz sicher, was Sie meinen "Google mag diese Technik wirklich nicht". Um das Overlay zu implementieren, das in meinem Fall eine Art Polygon ist, befolge ich das Beispiel in der Google Maps Javascript API Dokumentation [hier] (https://developers.google.com/maps/documentation/javascript/overlays #CustomOverlays). Das EventReceiverOverlay wird mit dem google.maps.OverlayView-Prototyp erstellt, daher sollte es nicht meine Leinwand und ihre Leinwand geben, sondern nur unsere gemeinsame, die durch Aufrufen der hier überschriebenen Zeichenmethode aktualisiert wird. – vicould

+0

Zuerst dachte ich, dass Sie ein zusätzliches Element an das OverlayView anfügen würden. Also stimme ich zu, dass dies * funktionieren * sollte. Aber Sie werden feststellen, dass Googles Draw-Beispiel * nicht * die interne "canvas_" -Eigenschaft manipuliert. Ich nehme an, der abschließende Unterstrich soll anzeigen, dass es ein privates Mitglied ist? Verwenden Sie stattdessen Ihre Punkte, um ein von Google genehmigtes Polygon zu erstellen und fügen Sie es zu Ihrer Karte hinzu. (Beispiele auf derselben Seite) – shovemedia

+0

Das Problem mit dem von Google genehmigten Polygon ist, dass Sie keinen Zugriff auf das zugehörige HTML-Element haben. Daher ist es nicht möglich, einen Listener hinzuzufügen (es sei denn, ich habe etwas übersehen). Auch in Chrome, Opera, Firefox und Safari, die älter als 5.1.4 sind, funktioniere ich perfekt. Für mich ist das Problem also spezifisch für Safari. – vicould