Heim  >  Artikel  >  Web-Frontend  >  Informationen zur Ereignisbehandlung von HTML5 Canvas

Informationen zur Ereignisbehandlung von HTML5 Canvas

不言
不言Original
2018-06-22 14:31:342224Durchsuche

Dieser Artikel stellt hauptsächlich die Ereignisverarbeitung von HTML5 Canvas vor. In diesem Artikel werden die Einschränkungen von Canvas, das Binden von Ereignissen an Canvas-Elemente, die isPointInPath-Methode, das Neuzeichnen von Schleifen und das Bubbling von Ereignissen usw. erläutert. Freunde in Not können sich darauf beziehen

DOM ist ein sehr wichtiger Teil des Web-Frontend-Bereichs und wird nicht nur bei der Verarbeitung von HTML-Elementen, sondern auch in der Grafikprogrammierung verwendet. Beispielsweise werden beim SVG-Zeichnen verschiedene Grafiken in Form von DOM-Knoten in die Seite eingefügt, was bedeutet, dass Grafiken mithilfe von DOM-Methoden manipuliert werden können. Wenn beispielsweise ein b0df1a4bdae36d21726841c97f474466-Element vorhanden ist, können Sie direkt mit jquery ein Klickereignis $('#p1').click(function(){…})" hinzufügen. Diese DOM-Verarbeitungsmethode ist für HTML5 nicht mehr anwendbar. Canvas verwendet einen anderen Satz von Mechanismen, egal wie viele Grafiken auf Canvas gezeichnet werden. Die Grafiken selbst sind tatsächlich Teil von Canvas Separat erhältlich, daher kann es nicht direkt an jemanden weitergegeben werden.

Einschränkungen von Canvas

In Canvas werden alle Grafiken auf dem Rahmen gezeichnet Die Zeichenmethode behandelt die gezeichneten Grafikelemente nicht als Rückgabewertausgabe, js kann die gezeichneten Grafikelemente nicht abrufen. Beispiel:

cvs = document.getElementById('mycanvas');
ctx = canvas.getContext('2d');
theRect = ctx.rect(10, 10, 100, 100);
ctx.stroke();
console.log(theRect);     //undefined

Dieser Code zeichnet zunächst ein Rechteck im Canvas-Tag Beachten Sie, dass die Rect-Methode zum Zeichnen von Grafiken keinen Rückgabewert hat. Wenn Sie die Entwicklertools des Browsers öffnen, können Sie auch sehen, dass im Canvas-Tag kein Inhalt hinzugefügt wurde und das Canvas-Element und der aktuelle Kontext nicht vorhanden sind Alle Inhalte, die auf die neuen Grafiken hinweisen.

Die üblicherweise im Frontend verwendeten DOM-Methoden sind also im Canvas nicht anwendbar. Wenn Sie beispielsweise auf das Rechteck im Canvas klicken, klicken Sie tatsächlich auf das Ganze Canvas-Element.

Ereignisse an das Canvas-Element binden

Da Ereignisse nur die Ebene des Canvas-Elements erreichen können, möchten Sie weitergehen und identifizieren, welche Grafik darin enthalten ist Wenn auf die Leinwand geklickt wird, müssen Sie Code zur Verarbeitung hinzufügen. Die Grundidee ist: Wenn das Ereignis auftritt, prüfen Sie, welche Grafiken die Position abdecken Im obigen Beispiel wird ein Rechteck gezeichnet, das die x-Achse 10-110 und den y-Achsenbereich 10-110 abdeckt. Solange die Maus innerhalb dieses Bereichs klickt, kann dies als Klicken auf das Rechteck angesehen werden , und das Klickereignis, das vom Rechteck verarbeitet werden muss, ist eigentlich relativ einfach, aber die Implementierung ist immer noch etwas kompliziert. Nicht nur die Effizienz des Prozesses , der Ereignistyp muss an einigen Stellen neu beurteilt werden und der Erfassungs- und Bubbling-Mechanismus innerhalb des Canvas muss neu definiert werden

Als Erstes müssen Ereignisse an das Canvas-Element gebunden werden, z Bestimmtes Ereignis innerhalb des Canvas. Um ein Klickereignis an eine Grafik zu binden, müssen Sie das Ereignis über das Canvas-Element weiterleiten:

cvs = document.getElementById('mycanvas');
cvs.addEventListener('click', function(e){
  //...
}, false);

Als nächstes müssen Sie den Ort bestimmen, an dem das Ereignisobjekt auftritt Die LayerY-Attribute des Ereignisobjekts e stellen die Koordinaten im internen Canvas-Koordinatensystem dar. Dieses Attribut wird jedoch von Opera nicht unterstützt und Safari plant, es zu entfernen, daher müssen wir einige kompatible Schreibmethoden erstellen:

function getEventPosition(ev){
  var x, y;
  if (ev.layerX || ev.layerX == 0) {
    x = ev.layerX;
    y = ev.layerY;
  } else if (ev.offsetX || ev.offsetX == 0) { // Opera
    x = ev.offsetX;
    y = ev.offsetY;
  }
  return {x: x, y: y};
}

//Hinweis: Um die obige Funktion verwenden zu können, müssen Sie die Position des Canvas-Elements auf absolut setzen.

Da wir nun die Koordinatenposition des Ereignisobjekts haben, müssen wir bestimmen, welche Grafiken im Canvas diese Koordinate abdecken.

isPointInPath-Methode

Die isPointInPath-Methode von Canvas kann bestimmen, ob die aktuelle Kontextgrafik eine bestimmte Koordinate abdeckt, wie zum Beispiel:

cvs = document.getElementById('mycanvas');
ctx = canvas.getContext('2d');
ctx.rect(10, 10, 100, 100);
ctx.stroke();
ctx.isPointInPath(50, 50);     //true
ctx.isPointInPath(5, 5);     //false

Fügen Sie als Nächstes eine hinzu Durch die Ereignisbeurteilung können Sie beurteilen, ob ein Klickereignis auf einem Rechteck auftritt:

cvs.addEventListener('click', function(e){
  p = getEventPosition(e);
  if(ctx.isPointInPath(p.x, p.y)){
    //点击了矩形
  }
}, false);

Das Obige ist die grundlegende Methode zur Behandlung von Canvas-Ereignissen, der obige Code weist jedoch Einschränkungen auf, da die isPointInPath-Methode nur den Pfad beurteilt Wenn also mehrere Grafiken in Canvas gezeichnet wurden, kann das Ereignis nur anhand des Kontexts der letzten Grafik beurteilt werden, z. B.

cvs = document.getElementById('mycanvas');
ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.rect(10, 10, 100, 100);
ctx.stroke();
ctx.isPointInPath(20, 20);     //true
ctx.beginPath();
ctx.rect(110, 110, 100, 100);
ctx.stroke();
ctx.isPointInPath(150, 150);     //true
ctx.isPointInPath(20, 20);     //false

Wie Sie dem obigen Code entnehmen können , die isPointInPath-Methode kann nur den Grafikpfad in der aktuellen Kontextumgebung identifizieren, und der zuvor gezeichnete Pfad kann nicht im Nachhinein beurteilt werden. Die Lösung für dieses Problem lautet: Wenn ein Klickereignis auftritt, zeichnen Sie alle Grafiken neu und verwenden Sie für jede gezeichnete Grafik die Methode isPointInPath, um zu bestimmen, ob die Ereigniskoordinaten innerhalb der Abdeckung der Grafiken liegen.

Loop-Neuzeichnen und Event-Bubbling

Um das Schleifen-Neuzeichnen zu implementieren, müssen die Grundparameter der Grafiken im Voraus gespeichert werden:

arr = [
  {x:10, y:10, width:100, height:100},
  {x:110, y:110, width:100, height:100}
];
cvs = document.getElementById('mycanvas');
ctx = canvas.getContext('2d');
draw();
function draw(){
  ctx.clearRech(0, 0, cvs.width, cvs.height);
  arr.forEach(function(v){
    ctx.beginPath();
    ctx.rect(v.x, v.y, v.width, v.height);
    ctx.stroke();
  });
}

Der obige Code speichert die Grundparameter der beiden Rechtecke im Voraus. Bei jedem Aufruf der Zeichenmethode werden diese Grundparameter in einer Schleife aufgerufen, um die beiden Rechtecke zu zeichnen. Die Methode „clearRect“ wird hier auch verwendet, um die Leinwand beim Neuzeichnen zu leeren. Als nächstes müssen Sie einen Ereignis-Proxy hinzufügen und beim Neuzeichnen die Methode isPointInPath für jeden Kontext verwenden:

cvs.addEventListener('click', function(e){
  p = getEventPosition(e);
  draw(p);
}, false);

Wenn das Ereignis eintritt, übergeben Sie die Koordinaten des Ereignisobjekts zur Verarbeitung an die Zeichenmethode. Hier müssen einige kleine Änderungen an der Zeichenmethode vorgenommen werden:

function draw(p){
  var who = [];
  ctx.clearRech(0, 0, cvs.width, cvs.height);
  arr.forEach(function(v, i){
    ctx.beginPath();
    ctx.rect(v.x, v.y, v.width, v.height);
    ctx.stroke();
    if(p && ctx.isPointInPath(p.x, p.y)){
      //如果传入了事件坐标,就用isPointInPath判断一下
      //如果当前环境覆盖了该坐标,就将当前环境的index值放到数组里
      who.push(i);
    }
  });
  //根据数组中的index值,可以到arr数组中找到相应的元素。
  return who;
}

在上面代码中,点击事件发生时draw方法会执行一次重绘,并在重绘过程中检查每一个图形是否覆盖了事件坐标,如果判断为真,则视为点击了该图形,并将该图形的index值放入数组,最后将数组作为draw方法的返回值。在这种处理机制下,如果Canvas里有N个图形,它们有一部分是重叠的,而点击事件恰巧发生在这个重叠区域上,那么draw方法的返回数组里会有N个成员。这时就有点类似事件冒泡的情况,数组的最后一个成员处于Canvas最上层,而第一个成员则在最下层,我们可以视为最上层的成员是e.target,而其他成员则是冒泡过程中传递到的节点。当然这只是最简单的一种处理方法,如果真要模拟DOM处理,还要给图形设置父子级关系。

以上就是Canvas事件处理的基本方法。在实际运用时,如何缓存图形参数,如何进行循环重绘,以及如何处理事件冒泡,都还需要根据实际情况花一些心思去处理。另外,click是一个比较好处理的事件,相对麻烦的是mouseover、mouseout和mousemove这些事件,由于鼠标一旦进入Canvas元素,始终发生的都是mousemove事件,所以如果要给某个图形单独设置mouseover或mouseout,还需要记录鼠标移动的路线,给图形设置进出状态。由于处理的步骤变得复杂起来,必须对性能问题提高关注。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

HTML5 canvas学习的实例介绍

angularJS结合canvas画图的实现

Das obige ist der detaillierte Inhalt vonInformationen zur Ereignisbehandlung von HTML5 Canvas. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn