Anzeige
Anzeige
News
Artikel merken

Fabric.js – Einführung in die mächtige JavaScript-Library

Mit unserer Mini-Serie für Web-Entwickler „WebDev hands on“ geben wir euch in Kooperation mit Microsoft modern.ie spannende Einblicke in Developer-Themen. Heute gibt es eine Einführung in Fabric.js.

Von Juriy Zaytsev
17 Min. Lesezeit
Anzeige
Anzeige

Dieser Artikel stellt Fabric.js vor – eine mächtige JavaScript-Library, die den Umgang mit dem HTML5-Element <canvas> zum Kinderspiel macht. Fabric stellt ein fehlendes Objektmodell zur Verfügung, sowie einen SVG Parser, eine Ebene für Interaktivität und eine ganze Suite voller unverzichtbarer Werkzeuge. Es ist ein Open-Source-Projekt unter der MIT-Lizenz, zu welchem über Jahre hinweg viel beigetragen wurde.

Anzeige
Anzeige

Ich habe vor drei Jahren angefangen, Fabric zu entwickeln, da mir die Arbeit mit der nativen Canvas-API viel zu kompliziert war. Ich erstellte einen interaktiven Design-Editor für die Website meines Startup-Unternehmens printio.ru, über die sich Kunden ihre eigene Kleidung gestalten können. Damals gab es die Art von Interaktivität, die ich mir vorstellte, nur in Flash-Anwendungen. Heutzutage allerdings gibt es nur sehr wenige Libraries, die auch nur annähernd an das herankommen, was mit Fabric möglich ist.

Warum Fabric?

Mit Canvas kann man heute absolut beeindruckende Grafiken im Web erstellen, aber die API, die dafür zur Verfügung steht, arbeitet auf einer enttäuschend niedrigen Ebene. Wenn man nur ein paar Grundformen auf eine Fläche zeichnen will und sie danach nicht mehr anfassen muss, ist das eine Sache. Braucht ihr aber auch nur die geringste Interaktivität, wollt ihr ein Bild zu einem späteren Zeitpunkt ändern oder müsst ihr komplexere Formen zeichnen, dann erhöht sich der Arbeitsaufwand erheblich. Fabric soll dieses Problem lösen.

Anzeige
Anzeige

Native Canvas-Methoden erlauben euch lediglich, einfache grafische Befehle abzusetzen und damit quasi im Blindflug die ganze Canvas-Bitmap zu verändern. Wollt ihr ein Rechteck? Dann schreibt ihr fillRect(left, top, width, height). Wollt ihr eine Linie? Dann verwendet ihr eine Kombination aus moveTo(left, top) und lineTo(x,y). Es ist gerade so, als ob ihr mit einem Pinsel Schicht für Schicht immer mehr Öl- und Acrylfarbe auftragt, jedoch mit sehr wenig Kontrolle.

Anzeige
Anzeige

Anstatt auf so niedriger Ebene zu arbeiten, bietet Fabric ein einfaches, aber gleichzeitig mächtiges Objektmodell an, das auf den nativen Methoden aufsetzt. Es kümmert sich um den Canvas-Zustand und das Rendern und lässt euch direkt mit den Objekten arbeiten.

Hier ist ein einfaches Beispiel, das den Unterschied demonstriert: Das folgende Codebeispiel zeigt, wie ein rotes Rechteck mittels nativer Canvas-API irgendwo auf den Canvas gezeichnet würde:

Anzeige
Anzeige
// Das Canvas-Element referenzieren (with id="c")
var canvasEl = document.getElementById('c');
// Einen 2D-Kontext erstellen um darauf zu zeichnen (die vorhin erwŠhnte "Bitmap")
var ctx = canvasEl.getContext('2d');
// Die FŸllfarbe fŸr den Kontext setzen
ctx.fillStyle = 'red';
// Ein gefŸlltes Rechteck auf Position 100,100 Pixel, mit einer Ausdehnung von 20x20 Pixel erstellen.
ctx.fillRect(100, 100, 20, 20);

Der untere Code zeigt euch, wie man genau das selbe mit Fabric erreicht. Das (identische) Ergebnis beider Herangehensweisen ist in Bild 1 gezeigt.

// Erstelle einen Wrapper um das native canvas-Element (with id="c")
var canvas = new fabric.Canvas('c');
// erstelle ein Rectangle-Objekt
var rect = new fabric.Rect({
  left: 100,
  top: 100,
  fill: 'red',
  width: 20,
  height: 20
});
// das Rechteck auf den canvas "hinzufŸgen". 
canvas.add(rect);
Rotes Rechteck gezeichnet mit Fabric oder nativen Methoden

Bild 1. Rotes Rechteck gezeichnet mit Fabric oder nativen Methoden

In diesem Beispiel ist der Code noch annähernd gleich lang, ihr könnt aber schon sehen, wie unterschiedlich die Arbeit mit Fabric ist. Mit den nativen Methoden arbeitet ihr auf dem Kontext – einem Objekt, das für die gesamte Canvas-Bitmap steht. In Fabric dagegen arbeiten ihr an Objekten: Ihr definieren nur Instanzen, ändert deren Eigenschaften und fügt sie dem Canvas hinzu. Ihr seht schon, dass sich in der Fabric-Welt alles um diese Objekte dreht.

Ein schlichtes Rechteck zeichnen zu lassen, ist viel zu einfach. Macht es doch ein bisschen interessanter und dreht die Form ein wenig. Probieren wir mal 45 Grad, zuerst mit den nativen Canvas-Methoden:

Anzeige
Anzeige
var canvasEl = document.getElementById('c');
var ctx = canvasEl.getContext('2d');
ctx.fillStyle = 'red';
ctx.translate(100, 100);
ctx.rotate(Math.PI / 180 * 45);
ctx.fillRect(-10, -10, 20, 20);

Und so würdet ihr das mit Fabric machen. (Siehe Bild 2 für die grafische Ausgabe)

var canvas = new fabric.Canvas('c');
// create a rectangle with angle=45
var rect = new fabric.Rect({
  left: 100,
  top: 100,
  fill: 'red',
  width: 20,
  height: 20,
  angle: 45
});
canvas.add(rect);
Ein rotes, gedrehtes Rechteck, mit Fabric oder mit den nativen Canvas-Methoden gezeichnet.

Bild 2. Ein rotes, gedrehtes Rechteck, mit Fabric oder mit den nativen Canvas-Methoden gezeichnet.

Lasst uns rekapitulieren: In Fabric müsst ihr lediglich den Wert des Objektwinkels auf 45 ändern. Mit den nativen Methoden ist da schon mehr Arbeit nötig. Denkt daran, dass ihr nicht mit Objekten arbeiten könnt. Stattdessen müsst ihr die Positionierung und den Winkel der gesamten Canvas-Bitmap (ctx.translate, ctx.rotate) euren Anforderungen anpassen. Erst dann zeichnet ihr das Rechteck. Vergesst dabei nicht, die Bitmap entsprechend zu versetzen (-10, -10), damit das gedrehte Rechteck immer noch am Punkt 100,100 gezeichnet wird. Damit es nicht zu langweilig wird, dürfen ihr beim Drehen der Canvas-Bitmap auch noch die Winkelgrade ins Bogenmaß umrechnen.

Sicher könnt ihr schon sehen, warum es Fabric gibt und wie viel nervigen, sich wiederholenden Low-Level-Kauderwelsch es einem spart.

Anzeige
Anzeige

Schauen wir uns noch ein Beispiel an: Verfolgung des Canvas-Zustands.

Was ist, wenn ihr irgendwann das Rechteck an eine andere Stelle auf dem Canvas verschieben wollt? Wie könntet ihr das tun, ohne mit Objekten zu arbeiten? Würdet ihr einfach einen weiteren fillRect-Befehl auf einer Canvas-Bitmap aufrufen? Bestimmt nicht. Ein neuer fillRect-Befehl legt ja einfach ein Rechteck über alles, was bereits auf dem Canvas gezeichnet wurde. Um das Rechteck zu verschieben, müsst ihr zuerst den ganzen vorher gezeichneten Inhalt löschen und dann das Rechteck an einer neuen Position zeichnen (siehe Bild 3).

var canvasEl = document.getElementById('c');
...
ctx.strokRect(100, 100, 20, 20);
...
// gesamten Canvas lšschen
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
ctx.fillRect(20, 50, 20, 20);

Und so würden Sie das mit Fabric machen:

Anzeige
Anzeige
var canvas = new fabric.Canvas('c');
...
canvas.add(rect);
...
rect.set({ left: 20, top: 50 });
canvas.renderAll();
Das rote Rechteck an einer neuen Stelle gezeichnet.

Bild 3. Das rote Rechteck an einer neuen Stelle gezeichnet.

Achtet auf folgenden wichtigen Unterschied: Mit Fabric müsst ihr nicht erst den Inhalt löschen, bevor ihr irgendeinen Inhalt ändert. Ihr arbeitet ja immernoch nur mit Objekten, deren Eigenschaften ihr einfach ändern könnt. Erst am Schluss lasst ihr den Canvas rendern, um ein neues Bild zu erhalten.

Objekte

Im obigen Kapitel habt ihr gesehen, wie man mit Rechtecken arbeitet, indem man Instanzen des fabric.Rect-Konstruktors erstellt. Fabric unterstützt natürlich auch noch andere Grundformen – Kreise, Dreiecke, Ellipsen und so weiter. Die Formen sind im Fabric-Namensraum als fabric.Circle, fabric.Triangle, fabric.Ellipse et cetera ansprechbar. Fabric stellt sieben Grundformen zur Verfügung:

  • fabric.Circle
  • fabric.Ellipse
  • fabric.Line
  • fabric.Polygon
  • fabric.Polyline
  • fabric.Rect
  • fabric.Triangle

Um einen Kreis zu zeichnen, braucht ihr nur ein Kreis-Objekt erstellen und es zum Canvas hinzufügen.

Anzeige
Anzeige
var circle = new fabric.Circle({
  radius: 20, fill: 'green', left: 100, top: 100
});
var triangle = new fabric.Triangle({
  width: 20, height: 30, fill: 'blue', left: 50, top: 50
});
canvas.add(circle, triangle);

Auf die selbe Weise könnt ihr alle anderen Grundformen erstellen. Bild 4 zeigt ein Beispiel, bei dem ein grüner Kreis an Position 100,100 gezeichnet wird und ein blaues Dreieck auf Position 50,50.

Ein blaues Dreieck und ein grüner Kreis mit Fabric gezeichnet.

Bild 4. Ein blaues Dreieck und ein grüner Kreis mit Fabric gezeichnet.

Objekte manipulieren

Grafische Objekte wie Rechtecke oder Kreise zu erstellen, ist nur der Anfang. Irgendwann werden Sie wahrscheinlich Ihre Objekte verändern müssen. Vielleicht soll eine bestimmte Aktion eine Zustandsveränderung auslösen oder eine Art von Animation abspielen. Oder vielleicht wollen Sie die Objekteigenschaften, wie Farbe, Transparenz, Größe oder Position, auf irgendwelche Mausaktionen hin ändern.

Fabric übernimmt für euch das Rendern des Canvas‘ und die Verwaltung der Zustände. Wir müssen nur die Objekte selbst verändern. Das vorherige Beispiel verwendete die set-Methode und zeigte, wie das Aufrufen von set({ left: 20, top: 50 }) das Objekt von seiner ursprünglichen Position verschob. In einer ähnlichen Weise könnt ihr die Eigenschaften eines Objektes ändern.

Anzeige
Anzeige

Wie zu erwarten, haben Fabric-Objekte Eigenschaften für Positionierung (left, top), Größe (width, height), Rendern (fill, opacity, stroke, strokeWidth), Skalierung und Drehung (scaleX, scaleY, angle) und Spiegelung (flipX, flipY). Will man also ein Objekt spiegeln, muss man lediglich die flip*-Eigenschaft auf true setzen.

Ihr könnt alle diese Eigenschaften mit einer get-Methode auslesen und mit einer set-Methode setzen. Das folgende Beispiel zeigt euch, wie einige der Eigenschaften des roten Rechtecks verändert werden. Bild 5 veranschaulicht das Ergebnis.

var canvas = new fabric.Canvas('c');
...
canvas.add(rect);
rect.set('fill', 'red');
rect.set({ strokeWidth: 5, stroke: 'rgba(100,200,200,0.5)' });
rect.set('angle', 15).set('flipY', true);
Rotes, gedrehtes und hellbau eingerahmtes Rechteck gezeichnet mit Fabric

Bild 5. Rotes, gedrehtes und hellbau eingerahmtes Rechteck gezeichnet mit Fabric

Zuerst setzen wir die Füllfarbe auf „red”. In der nächsten Zeile definieren wir Werte für strokeWidth und stroke, was dem Rechteck eine 5 Pixel breite Umrandung in einem Pastellgrün verleiht. Zum Schluss ändert der Code die Eigenschaften angle (Drehwinkel) und flipY (Spiegelung an der Y-Achse). Achtet darauf, dass alle drei Zeilen verschiedene Arten der Syntax demonstrieren.

Dies zeigt uns, dass set eine Universal-Methode ist. Ihr werden sie wahrscheinlich ziemlich oft verwenden und sie ist auch für ein einfaches Handhaben gedacht. Und was ist mit get-Methoden? Es gibt eine allgemeine get-Methode und auch ein paar spezifische get*-Methoden. Um die Breite eines Objekts auszulesen, würdet ihr get(‚width‘) oder getWidth() verwenden. Um den Wert für scaleX zu bekommen, könnt ihr get(’scaleX‘) oder getScaleX() verwenden, und so weiter. Es gibt eine Methode mit der selben Schreibweise wie getWidth oder getScaleX für jede der Objekteigenschaften, die „public” sind (stroke, strokeWidth, angle et cetera).

Ihr werdet vielleicht festgestellt haben, dass in den oberen Beispielen die Objekte gleich beim Erstellen des Objekts mit allen Eigenschaften konfiguriert, aber bei dem letzten Beispiel die Eigenschaften erst mit der set-Methode definiert wurden. Beides ist möglich und in seiner Wirkweise identisch. Ihr könnt ein Objekt entweder gleich beim Erstellen konfigurieren, oder erst nachher mit der set-Methode, wie ihr im folgenden Vergleich seht:

var rect = new fabric.Rect({ width: 10, height: 20, fill: '#f55', opacity: 0.7 });
// oder anders geschrieben, aber funktionell identisch.
var rect = new fabric.Rect();
rect.set({ width: 10, height: 20, fill: '#f55', opacity: 0.7 });

Standardwerte

An diesem Punkt fragt ihr euch vielleicht, was passiert, wenn ihr ein Objekt erstellt, ohne ihm irgendein „Konfigurationsobjekt” zu übergeben. Hat es trotzdem diese Eigenschaften?

Ja. Wenn gewisse Einstellungen während der Erstellung weggelassen werden, haben Objekte in Fabric immer eine Reihe von voreingestellten Eigenschaften. Ihr könnt den folgenden Code benutzen, um das zu sehen:

var rect = new fabric.Rect(); // Beachten Sie: Keine Eigenschaften werden per Argument Ÿbergeben. 
rect.getWidth(); // 0
rect.getHeight(); // 0
rect.getLeft(); // 0
rect.getTop(); // 0
rect.getFill(); // rgb(0,0,0)
rect.getStroke(); // null
rect.getOpacity(); // 1

Dieses Rechteck (im Code-Beispiel oben) hat nur voreingestellte Werte für seine Eigenschaften. Es ist positioniert an der Stelle 0,0, ist schwarz und komplett undurchsichtig, hat keinen Rand und keine Ausdehnung (width und height sind beide 0). Weil es keine Ausdehnung hat, könnt ihr es nicht auf dem Canvas sehen. Wenn ihr irgendwelche positiven Werte für width und height setzt, würdet ihr ein schwarzes Rechteck in der rechten oberen Ecke des Canvas sehen, genau wie in Bild 6.

Wie ein Standard-Rechteck aussieht, wenn ihm lediglich seine Größe (width, height) übergeben wurde.

Bild 6. Wie ein Standard-Rechteck aussieht, wenn ihm lediglich seine Größe (width, height) übergeben wurde.

Hierarchie und Vererbung

Fabric-Objekte existieren nicht völlig unabhängig voneinander. Sie stehen in einer ganz genauen Hierarchie. Die meisten Objekte erben von der Wurzel fabric.Object. Das Wurzelelement fabric.Object steht (mehr oder weniger) für eine zweidimensionale Form, die auf einer zweidimensionalen Canvas-Fläche positioniert ist. Es ist eine Einheit, die Eigenschaften wie left/top und width/height und eine ganze Menge anderer grafischer Charkterisika hat. Die aufgelisteten Eigenschaften für Objekte – fill, stroke, angle, opacity, flip* und so weiter – sind allen Fabric-Objekten gemein, die von fabric.Object Eigenschaften vererbt bekommen.

Die Vererbung erlaubt euch, Methoden für fabric.Object zu definieren und sie dann mit allen Kind-„Klassen“ zu teilen. Wollt ihr beispielsweise eine Methode getAngleInRadians für alle Objekte haben, würdet ihr sie einfach wie folgt für fabric.Object.prototype definieren:

fabric.Object.prototype.getAngleInRadians = function() {
  return this.getAngle() / 180 * Math.PI;
};
var rect = new fabric.Rect({ angle: 45 });
rect.getAngleInRadians(); // 0.785...
var circle = new fabric.Circle({ angle: 30, radius: 10 });
circle.getAngleInRadians(); // 0.523...
circle instanceof fabric.Circle; // true
circle instanceof fabric.Object; // true

Wie ihr sehen könnt, ist die Methode sofort für alle Instanzen verfügbar.

Auch wenn Kind-„Klassen” von fabric-Object erben, werden Methoden oft oder Eigenschaften auch speziell nur für die Kind-„Klassen” definiert. Zum Beispiel braucht fabric.Circle eine Eigenschaft radius. fabric.Image braucht die Methoden getElement und setElement, um das HTML-Element <img alt=““ />, wovon die Image-Instanz ursprünglich herkommt, auslesen und setzen zu können.

Canvas

Jetzt, nachdem ihr ein wenig mehr über Objekte gelernt habt, lasst uns zu Canvas zurückkehren.

Das erste, was ihr in allen Fabric-Beispielen seht, ist das Erstellen eines Canvas-Objekts – new fabric.Canvas(‚…‘). Das fabric.Canvas Objekt dient als Wrapper um das <canvas>-Element und regelt alle Fabric-Objekte auf diesem einen Canvas. Es nimmt dazu eine ID eines HTML-Elements und liefert eine Instanz von fabric.Canvas zurück.

Ihr könnt Objekte zum Canvas hinzufügen, sie von dort auslesen oder von ihm entfernen:

var canvas = new fabric.Canvas('c');
var rect = new fabric.Rect();
canvas.add(rect); // add object
canvas.item(0); // reference fabric.Rect added earlier (first object)
canvas.getObjects(); // get all objects on canvas (rect will be first and only)
canvas.remove(rect); // remove previously-added fabric.Rect

Objekte zu regeln ist die Hauptaufgabe von fabric.Canvas, man kann aber auch einiges damit konfigurieren. Ob ihr eine Hintergrundfarbe oder ein Hintergrundbild für den gesamten Canvas definieren, alle Inhalte eines bestimmten Bereichs abschneiden, andere Werte für width und height setzen, oder den Canvas als interaktiv oder nicht interaktiv setzen müsst – all diese Optionen (und noch mehr) könnt ihr für fabric.Canvas setzen, entweder zur Zeit der Objekterstellung oder später. Der folgende Code zeigt dazu ein Beispiel:

var canvas = new fabric.Canvas('c', {
  backgroundColor: 'rgb(100,100,200)',
  selectionColor: 'blue',
  selectionLineWidth: 2
  // ...
});
// or
var canvas = new fabric.Canvas('c');
canvas.backgroundImage = 'http://...';
canvas.onFpsUpdate = function(){ /* ... */ };
// ...

Interaktivität

Eines der Features, das Fabric einzigartig macht, ist eine Ebene für Interaktivität, die auf dem Objektmodell aufsetzt. Das Objektmodell besteht, um Programmierzugang und Manipulation von Objekten auf dem Canvas zu ermöglichen, aber außerhalb – auf der Benutzerebene – gibt es eine Möglichkeit, diese Objekte mit dem Mauszeiger (oder mit Berührungen auf Geräten mit Touchscreen) zu manipulieren. Sobald ihr einen Canvas mit dem Aufruf new fabric.Canvas(‚…‘) initialisiert, ist es möglich, Objekte auszuwählen (siehe Bild 7), sie zu ziehen, zu skalieren oder zu drehen und sogar zu gruppieren (siehe Bild 8), um alle zusammen in einem Schwung zu manipulieren.

Ein rotes, gedrehtes Rechteck in ausgewähltem Zustand (Steuerelemente sichtbar)

Bild 7. Ein rotes, gedrehtes Rechteck in ausgewähltem Zustand (Steuerelemente sichtbar)

Wenn ihr dem Anwender erlauben wollt, etwas auf dem Canvas herumzuziehen – zum Beispiel ein Bild –, müsst ihr lediglich den Canvas initialisieren und ihm ein Objekt hinzufügen. Es ist kein weiteres Konfigurieren oder Einstellen notwendig.

Zur Kontrolle dieser Interaktivität könnt ihr Fabrics Boole’sche Eigenschaft selection in Zusammenhang mit dem Canvas-Objekt verwenden und sie mit der Boole’schen Eigenschaft selectable für einzelne Objekte kombinieren:

 

var canvas = new fabric.Canvas('c');
...
canvas.selection = false; // Gruppierungsmšglichkeit deaktivieren
rect.set('selectable', false); // Ein Objekt nicht auswŠhlbar machen

Was aber, wenn ihr gar keine Interaktivitätsebene wollt? In diesem Fall könnt ihr statt fabric.Canvas einfach fabric.StaticCanvas schreiben. Die Syntax zur Initialisierung ist identisch zu der von fabric.Canvas:

var staticCanvas = new fabric.StaticCanvas('c');
staticCanvas.add(
  new fabric.Rect({
    width: 10, height: 20,
    left: 100, top: 100,
    fill: 'yellow',
    angle: 30
  }));

Dies erstellt quasi eine „Light“-Version von Canvas, ohne jeglicher Logik zum Behandeln von Ereignissen. Ihr könnt immernoch mit dem Objektmodell arbeiten, mit dem ihr Objekte hinzufügt, verändert oder entfernt, sowie die Einstellungen des Canvas selbst ändern könnt. All das funktioniert noch, nur das Behandeln von Ereignissen ist nicht mehr möglich.

Gleich behandle ich in diesem Artikel die Custom-Build-Möglichkeit. Ihr seht dann, dass ihr sogar eine abgespeckte Version von Fabric erstellen könnt, wenn StaticCanvas alles ist, was ihr braucht. Dies könnte eine nette Alternative sein, wenn ihr so etwas wie Diagramme oder Bilder ohne Interaktivität, aber mit Filter für eure Anwendung braucht.

Bilder

Rechtecke und Kreise zu einem Canvas hinzuzufügen ist nett, aber wie ihr euch schon denken könnt, macht es euch Fabric auch kinderleicht, mit Bildern zu arbeiten. Hier seht ihr, wie ihr eine Instanz eines fabric.Image-Objekts erstellen und sie zu einem Canvas hinzufügt. Zuerst den HTML-Code, dann das Javascript:

HTML:

<canvas id="c"></canvas>
<img src="my_image.png" id="my-image">

JavaScript:

var canvas = new fabric.Canvas('c');
var imgElement = document.getElementById('my-img');
var imgInstance = new fabric.Image(imgElement, {
  left: 100,
  top: 100,
  angle: 30,
  opacity: 0.85
});
canvas.add(imgInstance);
Leicht transparentes und gedrehtes Bild, gerendert mit Fabric

Bild 9. Leicht transparentes und gedrehtes Bild, gerendert mit Fabric

Beachtet, dass ihr ein Bild-Element an den fabric.Image-Kostruktor übergebt. Dies erstellt eine Instanz von fabric.Image, die genauso aussieht wie das Bild im Dokument. Aber zusätzlich habt ihr gleich left/top auf 100,100 gesetzt, einen Drehwinkel von 30 Grad bestimmt und die Transparenz auf 0.85 erhöht (Transparenz von 1.00 ist ganz sichtbar, 0.00 ist durchsichtig). Sobald das Bild dem Canvas hinzugefügt wird, wird es an der Position 100,100 mit einer Drehung von 30 Grad und einer leichten Transparenz dargestellt (Bild 9).

Wenn ihr nur eine URL zu einem Bild im Dokument habt, können Sie fabric.Image.fromURL verwenden:

fabric.Image.fromURL('my_image.png', function(oImg) {
  canvas.add(oImg);
});

Sieht doch recht simpel aus, oder? Einfach fabric.Image.fromURL aufrufen, mit einer URL zu einem Bild und einer Rückruffunktion, die aufgerufen wird, sobald das Bild geladen und erstellt ist. Der Rückruffunktion wird das bereits erstellte fabric.Image-Objekt als ihr erstes Argument übergeben. Jetzt könnt ihr es eurem Canvas hinzufügen oder zuerst verändern und dann hinzufügen, wie hier gezeigt:

fabric.Image.fromURL('my_image.png', function(oImg) {
  // scale image down, and flip it, before adding it onto canvas
  oImg.scale(0.5).setFlipX(true);
  canvas.add(oImg);
});

Path und PathGroup

Wir haben nun einfache Formen und Bilder besprochen. Aber was ist mit komplexen, reicheren Formen und Inhalten? Hier kommen Path und PathGroup ins Spiel, die ein starkes Team bilden.

Pfade bezeichnen in Fabric den Weg um eine Form, der gefüllt, umrandet und auf andere Weise verändert werden kann. Pfade bestehen aus einer Reihe von Befehlen, die im Grunde einen Stift nachahmen, der von einem Punkt zu einem anderen fährt. Mithilfe von Befehlen wie move, line, curve und arc können Pfade unglaublich komplexe Formen erstellen. Und unter der Verwendung von gruppierten Pfaden (PathGroup) eröffnen sich sogar noch mehr Möglichkeiten.

Pfade sind SVG -Elementen sehr ähnlich. Sie verwenden dieselben Befehle, können aus <path>-Elementen erzeugt sowie in <path>-Elemente gewandelt werden. Ich werde später mehr das SVG-Parsen schreiben. Momentan ist es ausreichend zu erwähnen, dass ihr wahrscheinlich nur selten Pfad-Instanzen von Hand erstellen werdet. Stattdessen werdet ihr den in Fabric eingebauten SVG-Parser verwenden. Aber zum Zwecke des Verständnisses, was Pfadobjekte sind, lasst uns hier eines per Hand erstellen (In Bild 10 sehen Sie das Ergebnis)

var canvas = new fabric.Canvas('c');
var path = new fabric.Path('M 0 0 L 200 100 L 170 200 z');
path.set({ left: 120, top: 120 });
canvas.add(path);
Einfacher Pfad, mit Fabric gerendert.

Bild 10. Einfacher Pfad, mit Fabric gerendert.

Hier erstellt ihr eine Instanz des fabric.Path-Objekts und übergebt ihm eine Zeichenkette mit Pfadanweisungen. Dies sieht vielleicht kryptisch aus, aber es ist eigentlich sehr einfach zu verstehen. M bezeichnet den move-Befehl und weist den unsichtbaren Stift an, zum Punkt 0,0 zu gehen. L steht für line und lässt den Stift eine Linie zum Punkt 200,100 zeichnen. Dann kommt ein zweites L, das ein Linie zum Punkt 170,200 zeichnet. Am Ende zwingt z den Stift, den aktuellen Pfad zu schließen und damit die Form zu vervollständigen.

Nachdem fabric.Path genau wie jedes andere Objekt in Fabric ist, könnt ihr auch einige seiner Eigenschaften verändern oder das Objekt sogar noch weiter modifizieren, wie hier in Bild 11 gezeigt.

...
var path = new fabric.Path('M 0 0 L 300 100 L 200 300 z');
...
path.set({ fill: 'red', stroke: 'green', opacity: 0.5 });
canvas.add(path);
Ein einfacher, modifizierter Pfad

Bild 11. Ein einfacher, modifizierter Pfad

Lasst uns, nur der Neugier wegen, eine etwas komplexere Pfadsyntax ansehen. Ihr werdet sehen, warum es vielleicht nicht die beste Idee ist, Pfade per Hand zu erstellen.

 

 

 

 

 

 

...
var path = new fabric.Path('M121.32,0L44.58,0C36.67,0,29.5,3.22,24.31,8.41
c-5.19,5.19-8.41,12.37-8.41,20.28c0,15.82,12.87,28.69,28.69,28.69c0,0,4.4,
0,7.48,0C36.66,72.78,8.4,101.04,8.4,101.04C2.98,106.45,0,113.66,0,121.32
c0,7.66,2.98,14.87,8.4,20.29l0,0c5.42,5.42,12.62,8.4,20.28,8.4c7.66,0,14.87
-2.98,20.29-8.4c0,0,28.26-28.25,43.66-43.66c0,3.08,0,7.48,0,7.48c0,15.82,
12.87,28.69,28.69,28.69c7.66,0,14.87-2.99,20.29-8.4c5.42-5.42,8.4-12.62,8.4
-20.28l0-76.74c0-7.66-2.98-14.87-8.4-20.29C136.19,2.98,128.98,0,121.32,0z');
canvas.add(path.set({ left: 100, top: 200 }));

Hier steht M immer noch für den move-Befehl. Der Stift fängt seine Zeichnungsreise am Punkt 121.32, 0. Dann kommt ein L-Befehl (line), der den Stift nach 44.58, 0 fahren lässt. Soweit so gut. Jetzt kommt der C-Befehl, der für „cubid bezier” steht. Dieser Befehl lässt den Stift eine Beziérkurve vom aktuellen Punkt nach 36.67, 0 zeichnen. Der Befehl benutzt 29.5, 3.22 als Kontrollpunkt für den Anfang einer Linie und 24.31, 8.41 als Kontrollpunkt am Ende der Linie. Diesem ganzen Prozess folgen dann noch ein Dutzende weiterer Beziér-Befehle, die schlussendlich eine nett-aussehende Pfeilform bilden, wie in Bild 12 gezeigt.

Ein komplexer Pfad, mit Fabric gerendert.

Bild 12. Ein komplexer Pfad, mit Fabric gerendert.

Wahrscheinlich werdet ihr nicht direkt mit solchen Ungetümen arbeiten. Stattdessen könnt ihr zum Beispiel die Methoden fabric.loadSVGFromString oder fabric.loadSVGFromURL verwenden, um eine ganze SVG-Datei zu laden und Fabrics SVG-Parser die mühsame Arbeit erledigen zu lassen, über all die SVG-Elemente zu gehen und entsprechende Pfadobjekte zu erstellen.

Während das Path-Objekt in Fabric üblicherweise ein SVG-<path>-Element darstellt, wird eine Sammlung an Pfaden, wie sie oft in SVG-Dokumenten vorkommt, mit einer Instanz von PathGroup (fabric.PathGroup) verkörpert. PathGroup ist nichts anderes als eine Gruppe von Path-Objekten und weil fabric.PathGroup alles von fabric.Objekt vererbt bekommt, kann es wie jedes andere Objekt einem Canvas hinzugefügt und auf die selbe Weise manipuliert werden.

Genau wie bei Pfaden, werden ihr kaum direkt an Pfadgruppen arbeiten. Aber solltet ihr nach dem Parsen eines SVG-Dokuments doch einmal über eine stolpern, wisst ihr nun genau was es ist und welchen Zweck es erfüllt.

Momentane Zusammenfassung

Ich habe nur ein wenig an der Oberfläche gekratzt, was die Möglichkeiten mit Fabric angeht. Ihr könnt jetzt leicht alle möglichen einfachen Formen, komplexen Formen oder Bilder erstellen, sie zu einem Canvas hinzufügen oder sie in irgendeiner Weise verändern: ihre Positionen, Ausdehnungen, Drehwinkel, Farben, Umrandungen, Transparenzen – was immer ihr wollt.

Im nächsten Artikel dieser Serie erläutere ich den Umgang mit Gruppen, Animation, Text, SVG-Parsen, Rendern, Ereignisse, Image-Filter und noch mehr.

In der Zwischenzeit könnt ihr euch ja schon mal die kommentierten Demos und Benchmarks ansehen, euch an der Diskussion bei Stack Overflow beteiligen oderr gleich in die Dokumentation, Wiki und den Source-Code eintauchen. Ihr könnt auch mehr über HTML5-Canvas im MSDN IE Developer Center lernen oder lest Rey Bangos auf Script Junkie.

Viel Spaß beim Experimentieren mit Fabric!

Über den Autor

Juriy Zaytsev ist ein leidenschaftlicher JavaScript-Entwickler, der in New York lebt. Er ist ein ehemaliges Kernmitglied von Prototype.js, Blogger auf perfectionkills.com, und der Schöpfer der Fabric.js-Canvas-Library. Zurzeit arbeitet Juriy an seinem Startup-Unternehmen Printio.ru und daran, dass es noch mehr Spaß macht, Fabric zu verwenden.

Hier könnt ihr Juriy finden:

Twitter – @kangax
Juriy’s Blog

Mehr zu diesem Thema
Fast fertig!

Bitte klicke auf den Link in der Bestätigungsmail, um deine Anmeldung abzuschließen.

Du willst noch weitere Infos zum Newsletter? Jetzt mehr erfahren

Anzeige
Anzeige
3 Kommentare
Bitte beachte unsere Community-Richtlinien

Wir freuen uns über kontroverse Diskussionen, die gerne auch mal hitzig geführt werden dürfen. Beleidigende, grob anstößige, rassistische und strafrechtlich relevante Äußerungen und Beiträge tolerieren wir nicht. Bitte achte darauf, dass du keine Texte veröffentlichst, für die du keine ausdrückliche Erlaubnis des Urhebers hast. Ebenfalls nicht erlaubt ist der Missbrauch der Webangebote unter t3n.de als Werbeplattform. Die Nennung von Produktnamen, Herstellern, Dienstleistern und Websites ist nur dann zulässig, wenn damit nicht vorrangig der Zweck der Werbung verfolgt wird. Wir behalten uns vor, Beiträge, die diese Regeln verletzen, zu löschen und Accounts zeitweilig oder auf Dauer zu sperren.

Trotz all dieser notwendigen Regeln: Diskutiere kontrovers, sage anderen deine Meinung, trage mit weiterführenden Informationen zum Wissensaustausch bei, aber bleibe dabei fair und respektiere die Meinung anderer. Wir wünschen Dir viel Spaß mit den Webangeboten von t3n und freuen uns auf spannende Beiträge.

Dein t3n-Team

fimbim

Die Liste der Github-Links führt zu 404ern. Ansonsten ne sehr geile Library!

Antworten

Melde dich mit deinem t3n Account an oder fülle die unteren Felder aus.

Bitte schalte deinen Adblocker für t3n.de aus!
Hallo und herzlich willkommen bei t3n!

Bitte schalte deinen Adblocker für t3n.de aus, um diesen Artikel zu lesen.

Wir sind ein unabhängiger Publisher mit einem Team von mehr als 75 fantastischen Menschen, aber ohne riesigen Konzern im Rücken. Banner und ähnliche Werbemittel sind für unsere Finanzierung sehr wichtig.

Schon jetzt und im Namen der gesamten t3n-Crew: vielen Dank für deine Unterstützung! 🙌

Deine t3n-Crew

Anleitung zur Deaktivierung
Artikel merken

Bitte melde dich an, um diesen Artikel in deiner persönlichen Merkliste auf t3n zu speichern.

Jetzt registrieren und merken

Du hast schon einen t3n-Account? Hier anmelden

oder
Auf Mastodon teilen

Gib die URL deiner Mastodon-Instanz ein, um den Artikel zu teilen.

Anzeige
Anzeige