Interne Canvas-Elemente können interaktive Ereignis-Listener nicht so bequem hinzufügen wie DOM-Elemente, da es in Canvas kein Elementkonzept gibt, sondern lediglich von Canvas gezeichnete Grafiken. Dies ist ein notwendiges Hindernis für die interaktive Entwicklung. Die Idee, das Klickereignis einer Grafik zu überwachen, ist sehr einfach. Hören Sie sich einfach das Klickereignis des Canvas-Elements selbst an und bestimmen Sie dann, in welcher Grafik sich die Klickkoordinaten befinden dann kann das grafische Klickereignis getarnt realisiert werden. In diesem Artikel werden drei Methoden vorgestellt, um festzustellen, ob sich der Koordinatenpunkt innerhalb einer Canvas-Grafik befindet.
VereinbarungDie drei in diesem Artikel vorgestellten Methoden eignen sich zur Identifizierung grafischer Klickereignisse mit unregelmäßigen Formen und unregelmäßigen Positionen auf der Leinwand. Für Szenen mit regelmäßigen Formen oder regelmäßigen Positionen muss es einfachere Implementierungen geben, auf die hier nicht eingegangen wird.
PixelmethodeDie Idee der Pixelerkennungsmethode besteht darin, mehrere Grafiken (falls mehrere vorhanden sind) außerhalb des Bildschirms separat auf der Leinwand zu zeichnen und die Methode getImageData() zu verwenden, um die Pixeldaten abzurufen und zu speichern. Wenn das Canvas-Element auf ein Klickereignis lauscht, können die Klickkoordinaten verwendet werden, um direkt das Pixel auf der Leinwand zu berechnen, auf dem der Klick stattgefunden hat, und dann die zuvor gespeicherten Grafikdaten zu durchlaufen, um zu sehen, ob der Alphawert dieses Pixels 0 ist. Wenn Es ist 0, was bedeutet, dass der Landepunkt nicht innerhalb der aktuellen Zahl liegt, andernfalls bedeutet es, dass der Punkt diese Zahl erreicht hat.
Methode zum Ermitteln der angeklickten Pixelzahl basierend auf den Klickkoordinaten:
Pixelzahl = (Ordinate-1) * Leinwandbreite + Abszisse
Wenn Sie beispielsweise auf einer Leinwand mit einer Breite von 5 auf die Koordinaten (3,3) klicken, beträgt die gemäß der obigen Formel erhaltene Pixelzahl (3-1) * 5 + 3 = 18, wie in der Abbildung gezeigt:
Da die von Canvas exportierten Grafikdaten jedes Pixel in einem Array aus 4 Zahlen in RGBA-Reihenfolge speichern, müssen Sie, wenn Sie auf den Alphawert eines bestimmten Pixels zugreifen möchten, nur den pIndex * 4 + 3-Wert dieses Arrays lesen. Wenn dieser Wert nicht 0 ist, bedeutet dies, dass das Pixel sichtbar ist, dh auf die Grafik geklickt wird.
Diese Methode bietet meiner Meinung nach die direktesten Ideen und die genauesten Ergebnisse und stellt keine Anforderungen an die Form der Grafiken. Allerdings weist diese Methode eine schwerwiegende Einschränkung auf, wenn Grafiken auf der Leinwand verschoben werden müssen. Datencaches müssen häufig erstellt werden, um die Genauigkeit der Ergebnisse sicherzustellen. Abhängig von der Leinwandgröße und der Anzahl der Grafiken wird die Leistung der Methode getImageData() zu einem ernsthaften Engpass. Wenn die Leinwandgrafik also statisch ist, ist diese Methode sehr gut geeignet, andernfalls ist die Verwendung dieser Methode nicht geeignet.
WinkelmethodeDas Prinzip der Winkelbeurteilungsmethode ist leicht zu verstehen. Wenn sich ein Punkt innerhalb eines Polygons befindet, sollte die Summe des Winkels zwischen dem Punkt und allen Eckpunkten des Polygons genau 360° betragen.
Der Berechnungsprozess lässt sich in die folgenden drei Schritte umwandeln:
1. Kombinieren Sie anhand der bekannten Polygonscheitelpunkte und bekannten Koordinaten die Koordinaten und Scheitelpunkte paarweise, um eine Dreipunktwarteschlange zu bilden.
2. Um den Winkel zwischen drei bekannten Punkten zu ermitteln, können Sie den Satz von Yu Xuan verwenden
3. Bestimmen Sie, ob die Summe der eingeschlossenen Winkel 360° beträgt
Jeder Schritt ist einfach und wird wie folgt umgesetzt:
//Berechnen Sie den Abstand zwischen zwei Punkten const getDistence = function (p1, p2) { return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2. y) * (p1.y - p2.y))};//Die Winkelmethode bestimmt, dass der Punkt innerhalb des Polygons liegt const checkPointInPolyline = (point, polylinePoints) => { let totalA = 0; const A = point; for (let i = 0; i < polylinePoints.length; i++) { let B, C; if (i === polylinePoints.length - 1) { B = { x: polylinePoints[i][0 ], y: polylinePoints[i][1] }; { x: polylinePoints[i][0], y: polylinePoints[i][1] }; } //Berechnen Sie den Winkel const angleA = Math.acos((Math.pow(getDistence(A, C), 2) + Math.pow(getDistence(A, B), 2) - Math.pow(getDistence(B, C), 2)) / (2 * getDistence(A, C) * getDistence(A, B))) totalA += angleA } //Beurteile die Summe von Winkel geben totalA zurück === 2 * Math.PI}Eine Einschränkung dieser Methode besteht darin, dass die Form ein konvexes Polygon sein muss. Wenn das Polygon kein konvexes Polygon ist, muss es vor der Berechnung in ein konvexes Polygon geschnitten werden, was komplizierter ist.
Eine ähnliche Idee ist die Flächenmethode. Wenn sich ein Punkt innerhalb eines Polygons befindet, sollte die Summe der Flächen des durch den Punkt und alle Eckpunkte des Polygons gebildeten Dreiecks gleich der Fläche des Polygons sein Es ist sehr mühsam, zuerst die Fläche des Polygons zu berechnen, daher kann diese Methode direkt übergeben werden.
Ray-MethodeDie Strahlenmethode ist eine Methode, die ich nicht genau erklären kann, die aber sehr einfach anzuwenden ist. Solange die Anzahl der Schnittpunkte zwischen einem Punkt und einer Seite des Polygons eine ungerade Zahl ist, liegt der Punkt innerhalb des Polygons. Beachten Sie, dass Sie nur die Anzahl der Fokuspunkte auf einer beliebigen Seite zählen müssen, beispielsweise auf der linken Seite. Diese Methode schränkt die Art des Polygons nicht ein, konvexe Polygone, konkave Polygone oder sogar Ringe sind akzeptabel.
Auch die Umsetzung ist ganz einfach:
const checkPointInPolyline = (point, polylinePoints) => { //Ray method let leftSide = 0; const A = point for (let i = 0; i < polylinePoints.length; i++) { let B, C; if (i = == polylinePoints.length - 1) { B = { x: polylinePoints[i][0], y: polylinePoints[i][1] }; polylinePoints[0][0], y: polylinePoints[0][1] } else { B = { x: polylinePoints[i][1] }; : polylinePoints[i + 1][0], y: polylinePoints[i + 1][1] } } //Linken Schnittpunkt beurteilen let sortByY = [By, Cy].sort((a,b) => ab) if (sortByY[0] < Ay && sortByY[1] > Ay){ if(Bx<Ax || Cx < Ax){ leftSide++ } } } return leftSide % 2 === 1}Es gibt einen Sonderfall der Strahlenmethode, der eine besondere Behandlung erfordert, wenn der Punkt auf einer Kante einer Mehrfachverformung liegt. Aber im Ingenieurwesen denke ich, dass es nicht verarbeitet werden muss, denn wenn der Benutzer zufällig auf die Grenze der Grafik klickt, dann denkt das Programm, dass er nicht geklickt hat und kann passieren.
ZusammenfassenDie oben genannten drei Methoden können alle die Klickerkennung unregelmäßiger Grafiken auf der Leinwand realisieren. Der Vorteil der Pixelmethode besteht darin, dass sie keine Formen auswählt und bestimmte Leistungsvorteile in statischen Szenen bietet. Die Winkelmethode hat nur einen theoretischen Wert und ist in der Technik am praktischsten , das nur wenige Einschränkungen aufweist und einfach zu implementieren ist. Meistens müssen Sie nur die Ray-Methode kennen.