Der HTML5-Standard ist schon lange nicht mehr verfügbar, aber es scheint, dass Canvas derzeit nicht an allzu vielen Stellen verwendet wird. Ein sehr wichtiger Grund ist, dass der Standard von Canvas noch nicht vollständig festgelegt ist und nicht für den groß angelegten Einsatz in Produktionsumgebungen geeignet ist. Die Vorteile von Canvas liegen jedoch auch auf der Hand. Beim Zeichnen von Diagrammen mit einer großen Anzahl von Elementen ist SVG beispielsweise aufgrund von Leistungsproblemen häufig nicht in der Lage, diese Aufgabe zu erfüllen Obwohl der Effekt relativ beeindruckend war, war dies aufgrund von Leistungsproblemen nicht möglich. Jeder Avatar ist ein DOM und die Animation wird von CSS3 gesteuert, was zu einer sehr geringen Leistung führt. Darüber hinaus können mit der Verbesserung der Hardwareleistung nach und nach Funktionen wie Video-Screenshots und Bildverarbeitung auf Webseiten implementiert werden. Die meisten Websites verwenden Flash, aber die Leistung von Flash ist auf Mac-Computern nicht hoch, und Sie müssen einige zusätzliche Kenntnisse erwerben Wissen. . Canvas verwendet JavaScript direkt zum Zeichnen und ist Mac-freundlich, sodass es als Nachfolger von Flash angesehen werden kann.
Canvas verwenden
Nachdem ich so viel gesagt habe: Was genau ist Canvas?
Canvas bedeutet auf Englisch „Leinwand“, aber das hier erwähnte Canvas ist ein neues Element in HTML5, auf dem Entwickler eine Reihe von Grafiken zeichnen können. Die Art und Weise, wie Canvas in eine HTML-Datei geschrieben wird, ist sehr einfach:
Das id-Attribut ist für alle HTML-Elemente verfügbar und die einzigen Attribute, die es gibt Bei Canvas gibt es die folgenden zwei (Breite bzw. Höhe steuern), sonst nichts. In Bezug auf die Kompatibilität gab CanIUse oben an, dass die Grundfunktionen derzeit von 90 % der von Benutzern verwendeten Browser unterstützt werden, sodass sie in den meisten Fällen bedenkenlos verwendet werden können.
Beachten Sie, dass Sie die mit Canvas gelieferten Breiten- und Höheneigenschaften verwenden müssen und kein CSS zur Steuerung verwenden, da die CSS-Steuerung zu einer Verformung des Canvas führt. Sie können versuchen, es mit PhptpShop zu vergleichen. Letzteres ändert die „Bildgröße“, während ersteres die richtige Methode zum Ändern der „Leinwandgröße“ ist. Das folgende Bild ist beispielsweise ein horizontales Zusammenfügen von drei Bildern: Das schwarze Feld ganz links ist das Originalbild mit einer Größe von 50 Pixel * 50 Pixel. Das mittlere Bild ist der Effekt der Änderung der Bildgröße auf 100 Pixel * 100 Pixel. aber für das Bild selbst Es wird gesagt, dass der Koordinatenbereich nicht größer geworden ist; der Bereich ganz rechts ist der richtige 100px * 100px Canvas.
Canvas Die meisten Zeichenmethoden haben nichts mit dem
Wir erhalten zuerst dieses Element:
var canvas = document.getElementById('canvas');
Und dann verwenden wir eine Methode, um den Eingang zu erhalten, der alle Canvas-APIs aufrufen kann:
var ctx = canvas.getContext('2d');
Sehen Sie, ob 2d vorhanden ist Ich war sehr gespannt, ob es 3D gibt? Es gibt keine Möglichkeit, 3D zu schreiben, aber wenn Sie die Tür zur 3D-Welt öffnen möchten, können Sie canvas.getContext('webgl') schreiben. Bei WebGL handelt es sich jedoch um eine Reihe von Standards, die auf OpenGL ES 2.0 basieren und sich völlig von diesem Artikel unterscheiden. Daher wird hier nicht darauf eingegangen.
Grundlegende Konzepte in Canvas
Koordinaten
sind nicht dasselbe wie das übliche kartesische Koordinatensystem in der Mathematik. Das Koordinatensystem von Canvas ist ein übliches Koordinatensystem in Computern sieht so aus:
Die obere linke Ecke der Leinwand ist (0,0), x erhöht sich nach rechts, y erhöht sich nach unten und x und y sind beide ganze Zahlen (Auch wenn es bei der Berechnung keine Ganzzahl ist, wird es beim Zeichnen als Ganzzahl behandelt) und die Einheit ist Pixel.
绘图
带大家怀旧一下。不知道有多少同学小时候玩过 logo 语言,在里面你可以控制一只小海龟在一块板子上行走、画画、提笔、落笔。Canvas 中也一样,你需要控制一只画笔的移动和绘制。然而 Canvas 更高级一些,你可以直接利用一些函数来画图,不用去控制那只画笔的位置。
Canvas 中的基本图形
通过上文定义的 ctx 变量可以干许多有意思的事情,我们先看看如何绘制一些基本图形。
线条
我们指定画笔移动到某一点,然后告诉画笔需要从当前这一点画到另一点。我们可以让画笔多次移动、绘制,最后统一输出到屏幕上。例子如下:
ctx.moveTo(10, 10); ctx.lineTo(150, 50); ctx.lineTo(10, 50); ctx.moveTo(10, 20); ctx.lineTo(40, 70); ctx.stroke();
上面的代码中,lineTo 是产生线条用的函数,执行完之后画笔就移到了线条的终点。需要注意的是,线条此时并没有显示在屏幕上,必须调用 stroke 才会显示。这样设计是有道理的,因为向屏幕上输出内容需要耗费大量的资源,我们完全可以先攒够一波 lineTo,最后用 stroke 放一个大的。
路径
绘制路径非常简单,只需要先告诉 ctx 一声“我要开始画路径了”,然后通过各种方法(例如 lineTo)绘制路径。如果需要画一个封闭路径,那就最后告诉 ctx一声:“我画完了,你把它封闭起来吧。”当然,不要忘记利用 stroke 输出到屏幕上。
一个简单的例子:
ctx.beginPath(); ctx.moveTo(10, 10); ctx.lineTo(150, 50); ctx.lineTo(10, 50); ctx.closePath(); ctx.stroke();
如果我不想只描绘路径线条,而是想填充整个路径呢?可以将最后一行的 stroke 改成 fill,这样就跟使用了画图中的油漆桶一样,封闭路径里面的内容就都被填充上颜色了:
ctx.fill();
弧 / 圆形
绘制弧的函数参数比较多:
ctx.arc(圆心 x 坐标, 圆心 y 坐标, 半径, 起始角度, 终止角度, 是否为逆时针);
注意,在 Canvas 的坐标系中,角的一边是以圆心为中心的水平向右的直线。角度单位均为弧度。例如下图,确定了圆心、起始角度(图中标明的锐角)和终止角度(图中标明的钝角),方向为逆时针,于是就有了这么一个弧。如果方向为顺时针,那么就会是一个跟它互补的、非常非常大的弧……
所以如果转了 2π 圈之后,弧就成了圆形,因此也可以使用绘制弧的方式来绘制圆形:
ctx.beginPath(); ctx.arc(圆心 x 坐标, 圆心 y 坐标, 半径, 0, Math.PI * 2, true); ctx.closePath();
最后一个参数随便填(当然也可以不填),因为不管是顺时针还是逆时针,转了 2π 圈之后都是一个圆。
矩形
如果只是想绘制一个横平竖直的矩形,可以使用下面的两个方法:
// 只描边 ctx.strokeRect(左上角 x 坐标, 左上角 y 坐标, 宽度, 高度); // 只填充 ctx.fillRect(左上角 x 坐标, 左上角 y 坐标, 宽度, 高度);
线条样式 / 填充样式
之前绘制的所有图形都是黑色的,但是 Canvas 肯定不止这么一种颜色(不然标准的制定者会被喷的很惨)。事实上,Canvas 可以单独设置线条样式和填充样式,分别使用的是 strokeStyle 和 fillStyle。可能的值有三种:纯色、渐变、图像。既然线条样式与填充样式的使用方法相同,那么下面统一以填充样式为例。如果想设置线条样式,直接将所有的 fillStyle 改成 strokeStyle 即可,里面的参数都不变。
/* 纯色填充 */ // 普通的颜色 ctx.fillStyle = '#0000ff'; // 带有透明度的颜色 ctx.fillStyle = 'rgba(64, 0, 127, 0.5)'; /* 渐变填充 */ // 设置渐变的尺寸(参数分别为起始点的 x 和 y、终止点的 x 和 y) var gradient = ctx.createLinearGradient(0, 0, 170, 0); // 设置过渡色,第一个参数是渐变的位置,第二个参数是颜色 gradient.addColorStop(0, 'magenta'); gradient.addColorStop(0.5, 'blue'); gradient.addColorStop(1.0, 'red'); // 设置填充样式 ctx.fillStyle = gradient; /* 图片填充 */ // 创建图片 var image = new Image; image.src = '/path/to/image.png'; // 创建图片笔触,可以指定图片的平铺方式,这里是横向平铺 var pattern = ctx.createPattern(image, 'repeat-x'); // 设置笔触填充 ctx.fillStyle = pattern;
关于渐变,除了代码中提到的线性渐变以外,还有 createRadialGradient,也就是径向渐变。
设置完填充样式之后,就可以使用 fill 来填充啦!如果设置的是线条样式,那么就可以使用 stroke 来描边。
当然,对于线条样式,还有个额外的方法叫 lineWidth 可以用来控制线条的宽度。
文字
要想在画布上画文字,首先需要知道所使用的字体和字号:
ctx.font = '30px Verdana';
然后就可以通过 strokeText 或者 fillText 来对字体描边或者填充字体。
ctx.strokeText("Hello Coding!", 23, 33); ctx.fillText("Hello Coding!", 23, 66);
图片
在 Canvas 中绘制图片有三种方法:
// 指定绘制位置 ctx.drawImage(image, x, y); // 指定绘制位置和图像宽高 ctx.drawImage(image, x, y, width, height); // 指定剪裁区域、绘制位置和图像宽高 ctx.drawImage(image, sx, sy, swidth, sheight, x, y, width, height);
参数的含义依次如下:
image: 要使用的 Image、Canvas 或 Video sx: 可选,开始剪切的 x 坐标 sy: 可选,开始剪切的 y 坐标 swidth: 可选,被剪切图像的宽度 sheight: 可选,被剪切图像的高度 x: 在画布上放置图像的 x 坐标 y: 在画布上放置图像的 y 坐标 width: 可选,要使用的图像的宽度 height: 可选,要使用的图像的高度
画布设置
细心的同学可能会发现,刚才有些属性是直接对 ctx 变量做设置,例如 ctx.lineWidth,只要设置了它,那么后续画出来的线条全都是这么个宽度。
其实,Canvas 的设置项还有许多,例如我们可以直接移动画布、旋转画布、设置全局的绘制透明度等等。这些设置还可以随时保存和恢复。
要注意的一点是,所有已经画在画布上的东西,是已经定死了的,不管之后再次进行任何设置都不会再改变。这个很像 Windows 下的画图程序。
废话不多说,直接上代码:
// 移动画布,其实就是移动坐标系 ctx.translate(往右移动的量, 往下移动的量); // 旋转画布,旋转中心为坐标系原点 ctx.rotate(顺时针旋转的角度); // 以坐标系原点为中心缩放画布 ctx.scale(横向放大倍数, 纵向放大倍数); // 设置绘制透明度,如果 fillStyle 等属性设置了透明度则会叠加 ctx.globalAlpha(零到一的小数); // 设置全局组合操作 ctx.globalCompositeOperation = 'lighter'; // 保存当前设置 ctx.save(); // 恢复上次保存的设置 ctx.restore();
移动、旋转、缩放其实就是在控制绘图的坐标系,如果你在调用这三个方法的时候,脑子里时刻有一个带刻度的坐标系,效果会非常好。
Tatsächlich folgt die Koordinatentransformation von Canvas dem Wissen der Computergrafik: Transformationsmatrix. Einfach ausgedrückt kann eine Koordinate als Matrix betrachtet werden. Die der Koordinate entsprechende Matrix kann mit der Transformationsmatrix multipliziert werden, um die Koordinate zu transformieren. Um die Effizienz der Berechnung zu verbessern, können Sie nach der Kombination mehrerer Transformationen zunächst die Transformationsmatrix berechnen und dann das aktuelle Koordinatensystem direkt über die Transformationsfunktion transformieren oder das Koordinatensystem über die setTransform-Funktion auf seinen Ausgangszustand zurücksetzen und dann ausführen Die Verwandlung. Der Inhalt der Transformationsmatrix würde den Rahmen dieses Artikels etwas sprengen.
Der globale Kombinationsvorgang ähnelt ein wenig der „Mischoption“ in PhotoShop. Die spezifische Implementierungsmethode wurde derzeit nicht vollständig bestimmt: gängige Browser verfügen über einheitliche Implementierungsmethoden: Quelle über, Quelle über, Ziel - vorbei, Ziel-aus, leichter, xor. Spezifische Verhaltensweisen finden Sie in der offiziellen Dokumentation von Mozilla. Da der Standard jedoch noch nicht vollständig festgelegt wurde, können andere Browser nicht garantieren, dass alle Verhaltensweisen mit den Standards von Mozilla übereinstimmen. Im Allgemeinen sind die gebräuchlicheren Versionen „Source-Over“ und „Lighter“, und die Standards dieser beiden sind in der Browserbranche unbestritten.
Das Speichern und Wiederherstellen von Einstellungen macht ein bisschen Spaß. Zuerst müssen Sie etwas verstehen, das als „Stack“ bezeichnet wird.
Der Stapel ist ein eindimensionales Array, das nur aus einer Richtung bedient werden kann. Der Stapel ist zu Beginn leer. Wir können Elemente aus dieser Richtung in das Array schieben und nur das letzte Element (das oberste Element des Stapels) aus dieser Richtung herausholen. Natürlich darf die Anzahl der Pops nicht größer sein als die Anzahl der Pushs, denn wenn der Pop den unteren Rand des Stapels erreicht, befinden sich keine Elemente im Stapel und es macht zu diesem Zeitpunkt keinen Sinn, erneut zu poppen. Der Stapel hat viele Verwendungsmöglichkeiten, z. B. Klammerabgleich, Ausdrucksauswertung, Tiefensuche und sogar Funktionsaufrufe in den meisten Sprachen, die den Stapel verwenden.
Jedes Mal, wenn wir die Speicherfunktion aufrufen, verschieben wir tatsächlich die aktuellen globalen Einstellungen auf einen speziellen Stapel. Jedes Mal, wenn wir die Wiederherstellungsfunktion aufrufen, rufen wir den zuletzt gespeicherten Inhalt ab und überschreiben damit die aktuellen globalen Einstellungen . , sodass ganz oben im Stapel der zuletzt gespeicherte Inhalt steht. In manchen Situationen ist das Speichern und Wiederherstellen nützlich, wenn ich beispielsweise eine schiefe Figur zeichnen und dann mit dem Zeichnen der aufrechten Figur fortfahren muss. Auf diese Weise kann ich zuerst „Speichern“ aufrufen, dann drehen und dann nach dem Zeichnen der Figur wiederherstellen . Zeichnen Sie andere Formen.
Tatsächlich verfügt Canvas auch über viele Methoden, z. B. toDataURL konvertiert den Inhalt auf der aktuellen Leinwand direkt in eine hexadezimale Daten-URL, getImageData konvertiert das Bild direkt in ein RGBA-Array zur Verwendung durch Bildverarbeitungsalgorithmen und putImageData wird Das RGBA-Array wird in ein Bild umgewandelt und auf der Leinwand usw. angezeigt. In Verbindung mit regelmäßigen JavaScript-Updates (vorzugsweise mit requestAnimationFrame anstelle von setInterval) können Animationseffekte erzeugt werden. Es gibt auch viele Canvas-Bibliotheken im Internet, die es Programmierern ermöglichen, einfacher eigene Spezialeffekte oder Funktionen auf Basis von Canvas zu schreiben. Hier möchte ich etwas sagen: Wie mächtig ist die Vorstellungskraft eines jeden, wie mächtig ist Canvas~