Was ist der einfachste Weg, einem Canvas-Element einen Click-Event-Handler hinzuzufügen, der die x- und y-Koordinaten des Klicks zurückgibt (relativ zum Canvas-Element)?
Safari, Opera und Firefox sind nicht erforderlich.
javascript
canvas
Tom
quelle
quelle
Antworten:
Edit 2018: Diese Antwort ist ziemlich alt und verwendet Überprüfungen für alte Browser, die nicht mehr benötigt werden, da die Eigenschaften
clientX
undclientY
in allen aktuellen Browsern funktionieren. Vielleicht möchten Sie Patriques Answer für eine einfachere, neuere Lösung überprüfen .Ursprüngliche Antwort:
Wie in einem Artikel beschrieben, den ich damals gefunden habe, aber nicht mehr existiert:
Hat für mich perfekt funktioniert.
quelle
Wenn Sie Einfachheit mögen, aber dennoch browserübergreifende Funktionen wünschen, hat diese Lösung für mich am besten funktioniert. Dies ist eine Vereinfachung der @ Aldekein-Lösung, jedoch ohne jQuery .
quelle
getBoundingClientRect
gibt Positionen relativ zum Ansichtsfenster zurück? Dann war meine Vermutung falsch. Ich habe es nie getestet, da dies für mich nie ein Problem war, und ich wollte andere Leser freundlich vor einem potenziellen Problem warnen, das ich gesehen habe, aber ich danke Ihnen für Ihre Klarstellung.var canvas = document.getElementById('canvasID'); canvas.addEventListener("mousedown", function (e) { getCursorPosition(canvas, e);});
Update (05.05.16): Die Antwort von patriques sollte stattdessen verwendet werden, da sie sowohl einfacher als auch zuverlässiger ist.
Da die Leinwand nicht immer relativ zur gesamten Seite gestaltet ist,
canvas.offsetLeft/Top
gibt sie nicht immer das zurück, was Sie benötigen. Es wird die Anzahl der Pixel zurückgegeben, um die es relativ zu seinem offsetParent-Element versetzt ist. Dies kann so etwas wie eindiv
Element sein, das die Zeichenfläche mit einemposition: relative
angewendeten Stil enthält. Um dies zu berücksichtigen, müssen Sie die Kette vonoffsetParent
s durchlaufen , beginnend mit dem Canvas-Element selbst. Dieser Code funktioniert perfekt für mich, wurde in Firefox und Safari getestet, sollte aber für alle funktionieren.Die letzte Zeile erleichtert das Abrufen der Mauskoordinaten relativ zu einem Canvas-Element. Alles, was benötigt wird, um die nützlichen Koordinaten zu erhalten, ist
quelle
event.offsetX
undevent.offsetY
Attribute, daher habe ich Ihre Lösung durch Hinzufügen geändertif (event.offsetX !== undefined && event.offsetY !== undefined) { return {x:event.offsetX, y:event.offsetY}; }
. sieht aus wie es funktioniert.event.offsetX
undevent.offsetY
das funktioniert auch in IE9. Für Firefox (getestet mit v13) können Sieevent.layerX
und verwendenevent.layerY
.canvasX = event.pageX - totalOffsetX - document.body.scrollLeft; canvasY = event.pageY - totalOffsetY - document.body.scrollTop;
Moderne Browser erledigen dies jetzt für Sie. Chrome, IE9 und Firefox unterstützen das OffsetX / Y wie folgt und übergeben das Ereignis vom Click-Handler.
Die meisten modernen Browser unterstützen auch LayerX / Y, Chrome und IE verwenden jedoch LayerX / Y für den absoluten Versatz des Klicks auf die Seite, einschließlich Rand, Auffüllung usw. In Firefox sind LayerX / Y und OffsetX / Y gleichwertig, der Offset jedoch nicht existiert bisher nicht. Aus Gründen der Kompatibilität mit etwas älteren Browsern können Sie Folgendes verwenden:
quelle
Nach frischer Quirksmode der
clientX
undclientY
sind Methoden in allen gängigen Browsern unterstützt. Also, hier ist es - der gute, funktionierende Code, der in einem Bildlauf-Div auf einer Seite mit Bildlaufleisten funktioniert:Dies erfordert auch jQuery für
$(canvas).offset()
.quelle
Ich habe eine vollständige Demostration erstellt, die in jedem Browser mit dem vollständigen Quellcode der Lösung dieses Problems funktioniert: Koordinaten eines Mausklicks auf Canvas in Javascript . Um die Demo zu testen, kopieren Sie den Code und fügen Sie ihn in einen Texteditor ein. Speichern Sie es dann als example.html und öffnen Sie die Datei schließlich mit einem Browser.
quelle
Hier ist eine kleine Modifikation der Antwort von Ryan Artecona für Leinwände mit variabler (%) Breite:
quelle
Seien Sie vorsichtig bei der Koordinatenkonvertierung. In einem Klickereignis werden mehrere nicht browserübergreifende Werte zurückgegeben. Die Verwendung von clientX und clientY allein reicht nicht aus, wenn das Browserfenster gescrollt wird (überprüft in Firefox 3.5 und Chrome 3.0).
Dieser Artikel im Quirks-Modus bietet eine korrektere Funktion, die entweder pageX oder pageY oder eine Kombination von clientX mit document.body.scrollLeft und clientY mit document.body.scrollTop verwenden kann, um die Klickkoordinate relativ zum Dokumentursprung zu berechnen.
UPDATE: Außerdem beziehen sich offsetLeft und offsetTop auf die gepolsterte Größe des Elements und nicht auf die Innengröße. Eine Zeichenfläche mit dem angewendeten Stil padding: meldet den oberen linken Rand ihres Inhaltsbereichs nicht als offsetLeft. Es gibt verschiedene Lösungen für dieses Problem. Am einfachsten ist es, alle Rahmen-, Auffüll- usw. Stile auf der Leinwand selbst zu löschen und sie stattdessen auf ein Feld anzuwenden, das die Leinwand enthält.
quelle
Ich bin mir nicht sicher, wozu all diese Antworten gut sind, die übergeordnete Elemente durchlaufen und alle möglichen seltsamen Dinge tun .
Die
HTMLElement.getBoundingClientRect
Methode wurde entwickelt, um die tatsächliche Bildschirmposition eines Elements zu handhaben. Dies beinhaltet das Scrollen, so dass Dinge wiescrollTop
nicht benötigt werden:Normales Bild
Der einfachste Ansatz wurde bereits hier veröffentlicht. Dies ist korrekt, solange keine wilden CSS- Regeln beteiligt sind.
Umgang mit gestreckter Leinwand / Bild
Wenn die Bildpixelbreite nicht mit der CSS-Breite übereinstimmt, müssen Sie ein gewisses Verhältnis auf die Pixelwerte anwenden:
Solange die Leinwand keinen Rand hat, funktioniert sie für gestreckte Bilder (jsFiddle) .
Umgang mit CSS-Rändern
Wenn die Leinwand einen dicken Rand hat, werden die Dinge wenig kompliziert . Sie müssen den Rand buchstäblich vom Begrenzungsrechteck abziehen. Dies kann mit .getComputedStyle erfolgen . Diese Antwort beschreibt den Prozess .
Die Funktion wächst dann ein wenig:
Ich kann mir nichts vorstellen, was diese endgültige Funktion verwirren würde. Sehen Sie sich bei JsFiddle .
Anmerkungen
Wenn Sie die nativen
prototype
s nicht ändern möchten, ändern Sie einfach die Funktion und rufen Sie sie auf(canvas, event)
(und ersetzen Sie siethis
durchcanvas
).quelle
Hier ist ein sehr schönes Tutorial-
http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
hoffe das hilft!
quelle
width
/height
Overriden, ist aber dennoch eine der besten Lösungen.Mit jQuery im Jahr 2016 mache ich Folgendes, um Klickkoordinaten relativ zur Zeichenfläche zu erhalten:
Dies funktioniert, da sowohl Canvas Offset () als auch jqEvent.pageX / Y unabhängig von der Bildlaufposition relativ zum Dokument sind.
Beachten Sie, dass diese Koordinaten nicht mit den logischen Canvas- Koordinaten übereinstimmen, wenn Ihre Zeichenfläche skaliert ist . Um diese zu erhalten, würden Sie auch tun:
quelle
Das ist also sowohl einfach als auch etwas komplizierter als es scheint.
Zunächst einmal gibt es hier meist zusammengeführte Fragen
So erhalten Sie elementbezogene Mauskoordinaten
So erhalten Sie Canvas-Pixel-Mauskoordinaten für die 2D-Canvas-API oder WebGL
Also, Antworten
So erhalten Sie elementbezogene Mauskoordinaten
Ob das Element eine Zeichenfläche ist, die relative Mauskoordinaten für Elemente abruft, ist für alle Elemente gleich.
Es gibt 2 einfache Antworten auf die Frage "Wie man Canvas-relative Mauskoordinaten erhält"
Einfache Antwort # 1 verwenden
offsetX
undoffsetY
Diese Antwort funktioniert in Chrome, Firefox und Safari. Im Gegensatz zu allen anderen Ereigniswerten
offsetX
undoffsetY
berücksichtigen CSS-Transformationen.Das größte Problem mit
offsetX
undoffsetY
ist, dass sie ab 2019/05 bei Touch-Ereignissen nicht mehr vorhanden sind und daher nicht mit iOS Safari verwendet werden können. Sie existieren auf Zeigerereignissen, die in Chrome und Firefox existieren, aber nicht in Safari, obwohl Safari anscheinend daran arbeitet .Ein weiteres Problem ist, dass sich die Ereignisse auf der Leinwand selbst befinden müssen. Wenn Sie sie auf ein anderes Element oder das Fenster setzen, können Sie die Leinwand später nicht als Bezugspunkt auswählen.
Einfache Antwort # 2 verwenden
clientX
,clientY
undcanvas.getBoundingClientRect
Wenn Sie nicht die nächste einfachste Antwort über CSS - Transformationen ist es egal ist zu rufen
canvas. getBoundingClientRect()
und subtrahiert links abclientX
undtop
vonclientY
da inDies funktioniert, solange keine CSS-Transformationen vorhanden sind. Es funktioniert auch mit Touch-Ereignissen und damit auch mit Safari iOS
So erhalten Sie Canvas-Pixel-Mauskoordinaten für die 2D-Canvas-API
Dazu müssen wir die oben angegebenen Werte verwenden und die Größe der angezeigten Leinwand in die Anzahl der Pixel in der Leinwand selbst konvertieren
mit
canvas.getBoundingClientRect
undclientX
undclientY
oder mit
offsetX
undoffsetY
Hinweis: Fügen Sie der Leinwand in keinem Fall Auffüllungen oder Ränder hinzu. Dadurch wird der Code massiv kompliziert. Anstatt dass Sie einen Rand oder eine Polsterung wünschen, umgeben Sie die Leinwand in einem anderen Element und fügen Sie die Polsterung und / oder den Rand zum äußeren Element hinzu.
Arbeitsbeispiel mit
event.offsetX
,event.offsetY
Code-Snippet anzeigen
Arbeitsbeispiel mit
canvas.getBoundingClientRect
undevent.clientX
undevent.clientY
Code-Snippet anzeigen
quelle
Ich empfehle diesen Link - http://miloq.blogspot.in/2011/05/coordinates-mouse-click-canvas.html
quelle
x = new Number()
? Der Code darunter, der neu zugewiesen wird,x
was bedeutet, dass die zugewiesene Nummer sofort verworfen wirdVerwenden Sie in Prototype cumulativeOffset (), um die von Ryan Artecona oben erwähnte rekursive Summierung durchzuführen.
http://www.prototypejs.org/api/element/cumulativeoffset
quelle
Sie könnten einfach tun:
Dadurch erhalten Sie die genaue Position des Mauszeigers.
quelle
Siehe Demo unter http://jsbin.com/ApuJOSA/1/edit?html,output .
quelle
Hier sind einige Modifikationen der obigen Lösung von Ryan Artecona.
quelle
Zunächst benötigen Sie, wie andere gesagt haben, eine Funktion, um die Position des Canvas-Elements zu ermitteln . Hier ist eine Methode, die etwas eleganter ist als einige der anderen auf dieser Seite (IMHO). Sie können jedes Element übergeben und seine Position im Dokument abrufen:
Berechnen Sie nun die aktuelle Position des Cursors relativ dazu:
Beachten Sie, dass ich die generische
findPos
Funktion vom Ereignisbehandlungscode getrennt habe . ( Wie es sein sollte . Wir sollten versuchen, unsere Funktionen auf jeweils eine Aufgabe zu beschränken.)Die Werte von
offsetLeft
undoffsetTop
sind relativ zuoffsetParent
, was ein Wrapper-div
Knoten sein könnte (oder irgendetwas anderes). Wenn es kein Element gibt, das das Element umschließt, sindcanvas
sie relativ zum Elementbody
, sodass kein Versatz zum Subtrahieren vorhanden ist. Aus diesem Grund müssen wir die Position der Leinwand bestimmen, bevor wir etwas anderes tun können.Ähnlich
e.pageX
unde.pageY
geben Sie die Position des Cursors relativ zum Dokument an. Aus diesem Grund subtrahieren wir den Versatz der Leinwand von diesen Werten, um die wahre Position zu erhalten.Eine Alternative für positionierte Elemente besteht darin, die Werte von
e.layerX
und direkt zu verwendene.layerY
. Dies ist aus zwei Gründen weniger zuverlässig als die oben beschriebene Methode:quelle
ThreeJS r77
Nachdem ich viele Lösungen ausprobiert habe. Das hat bei mir funktioniert. Könnte jemand anderem helfen, also zu posten. Habe es von hier bekommen
quelle
Hier ist eine vereinfachte Lösung (dies funktioniert nicht mit Rahmen / Scrollen):
quelle
Ich habe eine Anwendung mit einer Leinwand über einem PDF erstellt, die viele Größenänderungen der Leinwand beinhaltete, wie z. B. das Vergrößern und Verkleinern des PDF-Dokuments, und im Gegenzug musste ich bei jedem Vergrößern / Verkleinern von PDF die Größe der Leinwand ändern, um die Größe anzupassen Größe des PDFs, ich habe viele Antworten in stackOverflow durchgesehen und keine perfekte Lösung gefunden, die das Problem schließlich lösen wird.
Ich habe rxjs und Angular 6 verwendet und keine spezifische Antwort für die neueste Version gefunden.
Hier ist das gesamte Code-Snippet, das für jeden hilfreich wäre, der rxjs nutzt, um auf Leinwand zu zeichnen.
Und hier ist das Snippet, das die Mauskoordinaten im Verhältnis zur Größe der Leinwand korrigiert, unabhängig davon, wie Sie die Leinwand vergrößern / verkleinern.
quelle
Hey, das ist im Dojo, nur weil ich den Code bereits für ein Projekt hatte.
Es sollte ziemlich offensichtlich sein, wie man es wieder in Nicht-Dojo-Vanille-JavaScript konvertiert.
Hoffentlich hilft das.
quelle