Wie wir alle wissen, ist eine Leinwand eine Bitmap. In einer Bitmap können wir verschiedene Dinge zeichnen, darunter Bilder, Linien usw. Was sollen wir also tun, wenn wir einem bestimmten Bild im Canvas ein Klickereignis hinzufügen möchten? Und js kann nur Canvas-Ereignisse überwachen. Offensichtlich existiert dieses Bild nicht und das Bild im Dom wird nur in die Canvas gezeichnet. Als nächstes werde ich einfach die Ereignisbindung für jedes Bild innerhalb einer Leinwand implementieren.
Lassen Sie mich zunächst über das Implementierungsprinzip sprechen: Es bindet tatsächlich verwandte Ereignisse an die Leinwand. Durch Aufzeichnen der Koordinaten der Leinwand, auf der sich das Bild befindet, wird beurteilt, auf welches Bild das Ereignis einwirkt. Auf diese Weise ähnelt es ein wenig dem Event-Agenten. Allerdings ist die Umsetzung noch etwas kompliziert.
ps: Ich habe den folgenden Code in ts geschrieben. Sie können ihn einfach als es6 lesen. Sie können ihn überprüfen, ob er etwas anders ist.
Typescript-Dokumentation (Typescript ist wirklich einfach zu verwenden, ich empfehle Ihnen, mehr darüber zu erfahren).
1. Stellen Sie eine Verbindung zwischen Bild und Leinwand her (hier verwende ich Farbblöcke anstelle von Bildern)Hier müssen wir eine bestimmte Verbindung zwischen dem Farbblock und der Leinwand herstellen und nicht nur rendern. Notieren Sie außerdem die Koordinaten, Breite und Höhe des Farbblocks. Lassen Sie es uns Schritt für Schritt umsetzen
Schreiben Sie zunächst eine einfache HTML-Seite, um eine Leinwand zu erstellen:
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA -Compatible content=ie=edge> <title>canvas event</title> <style> html, body { height: 100%; #fff; display: block; margin: 0 auto; </style></head><body> <canvas width=500 height=500 id=canvas></canvas></body>
Als nächstes müssen wir eine Canvas-Klasse definieren. Welche Funktionen sollte diese Klasse haben?
Da die Farbblöcke auch einige eigene Parameter haben, definieren wir zur Erleichterung der Erweiterung auch eine Klasse für die Farbblöcke. Die für diesen Typ erforderlichen Funktionen sind:
Legen wir zunächst Breite, Höhe, Farbe, Koordinaten (x, y) und Canvas-Instanz fest.
Okay, fang an zu schreiben
// Canvas-Klasse class Canvas { blockList: Block[] ctx: any canvas: any createBlock (option) { option.Canvas = this this.blockList.push(new Block(option)) this.painting() } Rendering (Block) { // Farbblockfunktion rendern this.ctx.fillStyle = block.color this.ctx.fillRect(block.x, block.y, block.w, block.h) } painting () { // Alle Farbblöcke im Container auf der Leinwand rendern // Leinwand löschen (die alte sollte vor dem Rendern gelöscht werden) this.ctx.fillStyle = '#fff' this.ctx.fillRect(0, 0, this.canvas. width, this .canvas.height) this.blockList.forEach(ele => { this.rendering(ele) }) } Konstruktor (ele) { // Initialisierungsfunktion (die Eingabe ist Canvas) // Set Canvas this.canvas = ele this.ctx = this.canvas.getContext('2d') // Farbblockcontainer this.blockList = [] }}class Block { w: Zahl h: Zahl x: Zahl y: Zahl Farbe : string Canvas: Canvas-Hierarchie: Zahlenkonstruktor ({ w, h, x, y, color, Canvas }) { // Initialisiere und setze die farbblockbezogenen Eigenschaften this.w = w this.h = h this.x = x this.y = y this.color = Farbe this.Canvas = Canvas }}
Versuchen wir unten, eine Welle zu laufen
//Erstelle eine Canvas-Instanz und füge einen blauen Farbblock mit einer Breite und Höhe von 100 Pixel, Position (100.100), (300.100), roten und blauen Farbblöcken hinzu. var canvas = new Canvas(document.getElementById('canvas')) Canvas .createBlock({ // rot x: 100, y: 100, w: 100, h: 100, Farbe: '#f00' }) canvas.createBlock({ // blue x: 100, y: 100, w: 300, h: 100, color: '#00f' })
Die Laufergebnisse sind wie folgt:
2. Fügen Sie dem Farbblock ein Klickereignis hinzuSie können dem Farbblock hier kein Klickereignis direkt hinzufügen, daher müssen Sie Koordinaten verwenden, um zu bestimmen, auf welchen Farbblock gerade geklickt wird.
class Block { // ...Teil des Codes weglassen checkBoundary (x, y) { // Bestimmen Sie die Grenzmethode return x > this.x && x < (this.x + this.w) && y > this.y && y < (this.y + this.h) } mousedownEvent () { // Klicken Sie auf das Ereignis console.log(`Klicke auf den Farbblock mit der Farbe ${this.color}`) }}class Canvas { // .. .Teilcode-Konstruktor weggelassen (ele) { this.canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // Ereignisbindung (Hier gibt es eine Sache zu beachten. Ich habe hier die Bindungsmethode verwendet, die ist Um den this-Zeiger in der Methode „mousedownEvent“ auf „Canvas“ umzustellen) this.canvas.addEventListener('click', this.mousedownEvent.bind(this)) // Click event} mousedownEvent () { // Klickereignis const x = e.offsetX const y = e.offsetY // Hier werden die Koordinaten des Klicks an alle Farbblöcke übergeben und die Grenzbeurteilungsmethode wird verwendet, um zu bestimmen, ob der Klick innerhalb ist. Wenn ja, führen Sie die Ereignismethode des Farbblocks aus. this.blockList.forEach(ele => { if (ele.checkBoundary(x, y)) ele.mousedownEvent(e) }) }}
Bisher haben wir die Bindung entsprechender Klickereignisse an verschiedene Farbblöcke in verschiedenen Leinwänden implementiert. Dieses Klickereignis ist jedoch nicht perfekt, da wir das Konzept der Hierarchie noch nicht eingeführt haben, was bedeutet, dass beim Klicken auf zwei überlappende Farbblöcke beide ausgelöst werden. Daher müssen wir den Farbblöcken auch hierarchische Attribute hinzufügen. Wenn Sie auf einen Farbblock klicken, um den Farbblock zu ändern, wird die Ebene des Farbblocks auf die höchste Ebene angehoben.
class Block { // ...Einen Teil des Codekonstruktors weglassen ({ w, h, x, y, color, Canvas, hierarchy }) { // Eigenschaften für den Farbblock initialisieren und festlegen this.w = w this .h = h this. x = x this.y = y this.color = color this.Canvas = Canvas this.hierarchy = 0 }}class Canvas { // ...einen Teil des Codekonstruktors weglassen (ele) { this .canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // Ereignisbindung (Hier gibt es etwas zu beachten. Ich habe hier die Bindungsmethode verwendet, um den Zeiger this in der Methode mousedownEvent auf Canvas umzustellen) diese .canvas .addEventListener('click', this.mousedownEvent.bind(this)) // Click-Ereignis this.nowBlock = null // Aktuell ausgewählter Farbblock} createBlock (option) { // Farbblockfunktion erstellen (Block ist hier die Klasse des Farbblocks) option.Canvas = this // Die Ebene zum Erstellen des neuesten Farbblocks sollte die höchste sein option.hierarchy = this.blockList.length this.blockList.push(new Block (Option)) this.rendering() } mousedownEvent (e) { // Klickereignis const x = e.offsetX const y = e.offsetY // Holen Sie sich den Farbblock der höchsten Ebene im Punkt this.nowBlock = (this.blockList.filter(ele => ele.checkBoundary(x, y))).pop() // Wenn kein erfasster Farbblock vorhanden ist, beenden Sie ihn direkt, wenn (!this .nowBlock) return // Erhöhe die angeklickte Farbblockebene auf die höchste Stufe this.nowBlock.hierarchy = this.blockList.length // Neu anordnen (von klein nach groß) this.blockList.sort((a, b) = > a.hierarchy - b.hierarchy) // Hierarchie von 0 neu zuweisen this.blockList.forEach((ele, idx) => ele.hierarchy = idx) // In umgekehrter Reihenfolge neu sortieren und dann erneut rendern. this.painting() this.nowBlock.mousedownEvent(e) // Löst nur Ereignisse für den ausgewählten Farbblock aus}}// Hier müssen wir auch einen dritten Farbblock hinzufügen, der den roten Farbblock überlappt. canvas.createBlock({ x: 150, y: 150, w: 100, h: 100, Farbe: '#0f0'})
Der Code in der Methode „mousedownEvent“ in Canvas ist etwas kompliziert, hauptsächlich weil er etwas kompliziert ist.
Der Effekt nach dem Laufen ist wie folgt:
3. Ziehen Sie verschiedene Farbblöcke per Drag & DropOben haben wir implementiert, verschiedene Farbblöcke zu erhalten und deren Ebenen zu ändern. Als nächstes müssen wir das Ziehen von Farbblöcken implementieren, hauptsächlich um die Änderungen der Positionskoordinaten während der Mausbewegung und beim ersten Klicken mit der Maus zu ermitteln. Dieses Prinzip ist das gleiche wie bei der gewöhnlichen DOM-Drag-and-Drop-Implementierung.
Ermitteln Sie den Punkt, an dem auf den Farbblock geklickt wird, und den Abstand (disX, disY) vom linken und oberen Rand des Farbblocks.
Wenn sich die Maus bewegt, subtrahieren Sie (disX, disY) vom aktuellen Abstand der Maus vom linken und oberen Rand der Leinwand. Dies sind die x- und y-Koordinaten des Farbblocks.
class Block { // ...einen Teil des Codes weglassen mousedownEvent (e: MouseEvent) { /* Die Berechnungsmethode von disX und disY hier: e.offsetX ermittelt den Abstand zwischen dem Mausklick und der linken Seite der Leinwand und this.x ist der Farbblockabstand. Der Abstand links von der Leinwand. e.offsetX-this.x ist der Abstand links vom Farbblock. Dies sollte leicht zu verstehen sein*/ const disX = e.offsetX - this.x // Der Abstand von der linken Seite des Farbblocks, wenn darauf geklickt wird. const disY = e.offsetY - this.y // Der Abstand von der Oberseite von der Farbblock, wenn darauf geklickt wird // Bindet das Mausgleitereignis; hier ist mouseEvent.offsetX auch der Abstand zwischen der Maus und der linken Seite der Leinwand, mouseEvent.offsetX - disX ist die x-Koordinate des Farbblocks. Auf die gleiche Weise wird y auf die gleiche Weise berechnet. Zum Schluss einfach noch einmal rendern. document.onmousemove = (mouseEvent) => { this.x = mouseEvent.offsetX - disX this.y = mouseEvent.offsetY - disY this.Canvas.painting() } // Alle Ereignisse löschen, wenn die Maus losgelassen wird document.onmouseup = ( ) => { document.onmousemove = document.onmousedown = null } // console.log(`Angeklickter Farbblock 22` mit der Farbe ${this.color}) }}
Der Effekt ist wie folgt:
Der vollständige Code wird unten eingefügt (der HTML-Code und die aufrufenden Methoden werden nicht berücksichtigt). Bei diesem Beispiel handelt es sich lediglich um eine einfache Implementierung von Bindungsereignissen an den Inhalt im Canvas. Sie können komplexere Ereignisse implementieren, z. B. das Ersetzen von Farbblöcken durch Bilder. Zusätzlich zum Ziehen können Sie Bilder zoomen, drehen, löschen usw.
class Canvas { blockList: Block[] ctx: any canvas: any nowBlock: Block createBlock (option) { option.hierarchy = this.blockList.length option.Canvas = this this.blockList.push(new Block(option)) this. painting() } Rendering (Block) { this.ctx.fillStyle = block.color this.ctx.fillRect(block.x, block.y, block.w, block.h) } painting () { // Leinwand löschen this.ctx.fillStyle = '#fff' this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height) this.blockList.forEach(ele => { this.rendering(ele) }) } mousedownEvent (e: MouseEvent) { // Klickereignis const x = e.offsetX const y = e.offsetY // Holen Sie sich den Farbblock der höchsten Ebene im Punkt this.nowBlock = (this.blockList.filter(ele => ele.checkBoundary(x, y))).pop() // Wenn kein erfasster Farbblock vorhanden ist, beenden Sie ihn direkt, wenn (!this .nowBlock) return // Erhöhe die angeklickte Farbblockebene auf die höchste Stufe this.nowBlock.hierarchy = this.blockList.length // Neu anordnen (von klein nach groß) this.blockList.sort((a, b) = > a.hierarchy - b.hierarchy) // Hierarchie von 0 neu zuweisen this.blockList.forEach((ele, idx) => ele.hierarchy = idx) // In umgekehrter Reihenfolge neu sortieren und dann erneut rendern. this.painting() this.nowBlock.mousedownEvent(e) // this.blockList.forEach(ele => { // if (ele.checkBoundary(x, y)) ele.clickEvent(e) // }) } Konstruktor (ele) { this.canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // Ereignisbindung this.canvas.addEventListener('mousedown', this.mousedownEvent.bind(this)) }}class Block { w: Zahl h: Zahl x: Zahl y: Zahl Farbe: String Canvas: Canvas-Hierarchie: Zahlenkonstruktor ( { w, h, x, y, Farbe, Canvas, Hierarchie }) { this.w = w this.h = h this.x = x this.y = y this.color = Farbe this.Canvas = Canvas this.hierarchy = hierarchy } checkBoundary (x, y) { return x > this.x && x < (this.x + this.w) && y > this.y && y < (this.y + this.h) } mousedownEvent (e: MouseEvent) { const disX = e.offsetX - this.x const disY = e.offsetY - this.y document.onmousemove = (mouseEvent) => { this.x = mouseEvent.offsetX - disX this.y = mouseEvent.offsetY - disY this.Canvas.painting() } document.onmouseup = () => { document.onmousemove = document.onmousedown = null } // console.log(`Farbblock 22 mit Farbe ${this.color} wurde angeklickt`) }}
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für das Studium aller hilfreich ist. Ich hoffe auch, dass jeder das VeVb Wulin Network unterstützt.