20000 Star! A powerful and simple JS painting Library

From front-end Superman, author Rong Ding

Introduction

When we want to draw a basic simple shape on the Canvas, using Canvas won't feel cumbersome. However, when any form of interaction is required on the Canvas, drawing complex graphics and changing pictures in specific situations, it will become very difficult to use the native canvas API.

Fabric aims to solve this problem.

https://github.com/fabricjs/fabric.js

Fabric.js is a powerful and simple Javascript HTML5 canvas library. Fabric provides an interactive object model on top of canvas elements. Fabric also has SVG to canvas (and canvas to SVG) parsers.

For convenience, I will explain how to use Fabric through vue project

1, Installation

yarn add fabric -S
#or
npm i fabric -S

You can also download the latest js file on the official website and import it through the script tag

2, Use

<!-- html -->
<canvas id="canvas" width="500" height="500"></canvas>

2.1 draw a simple graph

Fabric offers 7 basic shapes:

  • fabric.Circle (circle)
  • fabric.Ellipse (ellipse)
  • fabric.Line
  • fabric.Polyline (multiple lines are drawn into graphics)
  • fabric.triangle (triangle)
  • fabric.Rect (rectangular)
  • fabric.Polygon
  • rectangle
// js

//Introducing fabric
import { fabric } from "fabric";

// Create a fabric instance
let canvas = new fabric.Canvas("canvas"); //You can zoom out and rotate with the mouse
// or
// let canvas = new fabric.StaticCanvas("canvas");// Fabric object without mouse interaction

// Create a rectangular object
let rect = new fabric.Rect({
    left: 200, //Distance to the left
    top: 200, //Distance from top
    fill: "green", //Fill color
    width: 200, //Rectangle width
    height: 200, //Rectangle height
});

// Add a rectangle to the canvas
canvas.add(rect);

You can see that the interface is filled with a green rectangle that can be zoomed in and out and rotated by the mouse. It is very convenient to configure the element style in the form of objects!

  • Circles and triangles
// Create a circular object
let circle = new fabric.Circle({
    left: 0, //Distance to the left
    top: 0, //Distance from top
    fill: "red", //Fill color
    radius: 50, //Radius of circle
});
// Create a triangle object
let triangle = new fabric.Triangle({
    left: 200, //Distance to the left
    top: 0, //Distance from top
    fill: "blue", //Fill color
    width: 100, //width
    height: 100, //height
});
// Add a graphic shape to the canvas
canvas.add(circle, triangle);

We can determine whether we can interact with related elements through the following attribute settings

canvas.selection = false; // Disable all selections
rect.set("selectable", false); // Just disable the selection of this rectangle

2.2 drawing pictures

There are mainly two ways to draw by url and img tag

//Draw pictures by url
fabric.Image.fromURL(
    //Local pictures need to be imported through require("./xxx.jpeg")
    "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.thaihot.com.cn%2Fuploadimg%2Fico%2F2021%2F0711%2F1625982535739193.jpg&refer=http%3A%2F%2Fimg.thaihot.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1630940858&t=e1d24ff0a7eaeea2ff89cedf656a9374",
    (img) => {
        img.scale(0.5);
        canvas.add(img);
    }
);
//You can also draw with labels
let img = document.getElementById("img");
let image = new fabric.Image(img, {
    left: 100,
    top: 100,
    opacity: 0.8,
});
canvas.add(image);

2.3 drawing through customized path

Before that, we need to understand the meaning of several parameters

  • M: "move" moves to a point
  • L: "line" draw lines x,y
  • C: curve
  • A: "arc" arc
  • z: closed path (similar to creating selection in PS)
let customPath = new fabric.Path("M 0 0 L 300 100 L 170 100  z");
customPath.set({
    left: 100,
    top: 100,
    fill: "green",
});
canvas.add(customPath);

let customPath = new fabric.Path(
    "M 0 0 L 300 100 L 170 100 L 70 300 L 20 200 C136.19,2.98,128.98,0,121.32,0 z"
);

It can be seen that through path drawing, we can make very complex graphics (but we usually don't use it. We usually use it to parse SVG and get the path recovery graphics)

animation

The first parameter is the attribute of the animation, the second parameter is the final position of the animation, and the third parameter is an optional object to specify the details of the animation: duration, callback, dynamic effect, etc.

The third parameter mainly includes

  • Duration defaults to 500ms. Can be used to change the duration of the animation.
  • from allows you to specify the starting value of the animation attribute (if we don't want to use the current value).
  • onComplete the callback after the animation ends.
  • easing dynamic effect function.

Absolute animation

let canvas = new fabric.Canvas("canvas");let rect = new fabric.Rect({    left: 400, //Distance from the left top: 200, / / distance from the top fill: "green", / / fill color width: 200, / / width height: 200, / / height}); rect.animate("left", 100, {    onChange: canvas.renderAll.bind(canvas),    duration: 1000,});canvas.add(rect);

Relative animation (the second parameter determines the final effect of animation through + =, - = and so on)

rect.animate("left", "+=100", {
    onChange: canvas.renderAll.bind(canvas),
    duration: 1000,
});

rect.set({ angle: 45 });
rect.animate("angle", "-=90", {
onChange: canvas.renderAll.bind(canvas),
duration: 2000,
});

Defines the animation's dynamic function

By default, the animation is executed using the ease in sine animation. If this is not what you need, fabric provides us with a lot of built-in animation effects. There are a lot of dynamic effects under fabric.util.ease. The commonly used ones include ease outbound, ease incubic, ease outbound cubic, ease inelastic, ease outbound elastic, ease inbound and ease outbound Expo

rect.animate("left", 100, {
    onChange: canvas.renderAll.bind(canvas),
    duration: 1000,
    easing: fabric.util.ease.easeOutBounce,
});

image filters

At present, Fabric provides us with the following built-in filters

  • BaseFilter basic filter
  • Blur blur
  • Brightness brightness
  • ColorMatrix color matrix
  • Contrast
  • Convolute
  • Gamma gamma
  • Grayscale
  • HueRotation hue rotation
  • Invert inversion
  • Noise
  • Pixelate
  • RemoveColor remove color
  • Resize resize
  • Saturation saturation

Single filter

fabric.Image.fromURL(require("./aaa.jpeg"), (img) => {
    img.scale(0.5);
    canvas.add(img);
});
fabric.Image.fromURL(require("./aaa.jpeg"), (img) => {
    img.scale(0.5);
    // Add Filter 
    img.filters.push(new fabric.Image.filters.Grayscale());
    // After the picture is loaded, apply the filter effect
    img.applyFilters();
    img.set({
        left: 300,
        top: 250,
    });
    canvas.add(img);
});

Overlay filter

The "filters" attribute is an array. We can use the array method to perform any required operations: remove filters (pop, slice, shift), add filters (push, unshift, slice), and even combine multiple filters. When we call applyFilters, any filters in the "filters" array will be applied one by one, so let's try to create an image that is both color biased and bright.

fabric.Image.fromURL(require("./aaa.jpeg"), (img) => {
    img.scale(0.5);
    // Add Filter 
    img.filters.push(
        new fabric.Image.filters.Grayscale(),
        new fabric.Image.filters.Sepia(), //Color deviation
        new fabric.Image.filters.Brightness({ brightness: 0.2 }) //brightness
    );
    // After the picture is loaded, apply the filter effect
    img.applyFilters();
    img.set({
        left: 300,
        top: 250,
    });
    canvas.add(img);
});

You can see that the effects of multiple filters are superimposed. Of course, fabric also supports custom filters. After 500 likes in this article, I will update the advanced article of fabric. Thank you for your support~

colour

Whether you use hexadecimal, RGB or RGBA colors, Fabric can handle them very well

define color

new fabric.Color("#f55");
new fabric.Color("#aa3123");
new fabric.Color("356333");
new fabric.Color("rgb(100,50,100)");
new fabric.Color("rgba(100, 200, 30, 0.5)");

Color conversion

new fabric.Color('#f55').toRgb(); // "rgb(255,85,85)"
new fabric.Color('rgb(100,100,100)').toHex(); // "646464"
new fabric.Color('fff').toHex(); // "FFFFFF"

We can also overlay with another color or convert it to a grayscale version.

let redish = new fabric.Color("#f55");
let greenish = new fabric.Color("#5f5");
redish.overlayWith(greenish).toHex(); // "AAAA55"
redish.toGrayscale().toHex(); // "A1A1A1"

Gradual change

Fabric supports gradients through the setGradient method and is defined on all objects. Calling setGradient('fill ', {...}) is like setting the "fill" value of an object.

let circle = new fabric.Circle({
  left: 100,
  top: 100,
  radius: 50
});

circle.setGradient("fill", {
    // Where the gradient starts
    x1: 0,
    y1: 0,
    // Where the gradient ends
    x2: circle.width,
    y2: 0,
    //Gradient color
    colorStops: {
        // The gradient range (0,0.1,0.3,0.5,0.75,1) can be between 0-1
        0: "red",
        0.2: "orange",
        0.4: "yellow",
        0.6: "green",
        0.8: "blue",
        1: "purple"
    },
});

text

The fabric.Text object provides richer functions for text than canvas, including:

  • Multi line support unfortunately, the native text method ignores creating a new line.
  • Text alignment text alignmentleft, center, right. Useful when working with multiline text.
  • Text background text background also supports text alignment.
  • Text decoration underline, underline, through line.
  • Line Highline height is useful when using multiline text.
  • Character spacing Char spacing makes text more compact or spaced.
  • The Subranges apply colors and attributes to children of text objects.
  • Multi byte Multibyte supports emoticons.
  • Interactive canvas editionon canvas editingyou can type text directly on the canvas.
let text = new fabric.Text(
    "hello everyone~This is Qianpu village\n I'm Rongding~\n A man who wants to be the king of development!",
    {
        left: 0,
        top: 200,
        fontFamily: "Comic Sans", //typeface
        fontSize: 50, //Font size
        fontWeight: 800, //Font thickness, you can use keywords ("normal", "bold") or numbers (100200400600800)
        shadow: "green 3px 3px 2px", //Text shadow, color, horizontal offset, vertical offset and blur size.
        underline: true, //Underline
        linethrough: true, //Delete line
        overline: true, //Upper scribe
        fontStyle: "italic", //Font style, normal or italic
        stroke: "#c3bfbf ", / / stroke color
        strokeWidth: 1, //Stroke width
        textAlign: "center", //text alignment
        lineHeight: 1.5, //Row height
        textBackgroundColor: "#91A8D0 ", / / text background color
    }
);
canvas.add(text);

event

In fabric, the on method is used to initialize events, and the off method is used to delete events.

Common events are as follows

  • "mouse:down" mouse pressed
  • The "object:add" object is added
  • after:render rendering is complete

There are also a lot of mouse events: "mouse:down", "mouse:move" and "mouse:up..." select relevant events: "before:selection:cleared", "selection:created". You can view the official documents for details

canvas.on("mouse:down", function(options) {
    canvas.clear();
    let text = new fabric.Text("You ordered me~", {
        left: 200,
        top: 200,
    });
    canvas.add(text);
    console.log(options.e.clientX, options.e.clientY);
});
canvas.on("mouse:up", function(options) {
    this.text = "You didn't order me 0.0";
    canvas.clear();
    let text = new fabric.Text("You didn't order me 0.0", {
        left: 200,
        top: 200,
    });
    canvas.add(text);
    console.log(options.e.clientX, options.e.clientY);
});

Fabric allows you to attach listeners directly to objects in the canvas.

let rect = new fabric.Rect({ width: 100, height: 50, fill: "green" });
rect.on("selected", function() {
    console.log("Oh, roar~You chose me");
});

let circle = new fabric.Circle({ radius: 75, fill: "blue" });
circle.on("selected", function() {
    console.log("Ha ha ha~You chose me");
});

Free painting

If the isDrawingMode property of Fabric canvas is set to true, the free drawing mode can be realized. In this way, the clicks and movements on the canvas will be immediately interpreted as pencils or brushes.

let canvas = new fabric.Canvas("canvas");
canvas.isDrawingMode = true;
canvas.freeDrawingBrush.color = "blue";
canvas.freeDrawingBrush.width = 5;

last

I'm glad to write this article. It's an article I use to summarize the knowledge points of fabric with great care. I hope this article will help you. At present, fabric is not very popular in China, but there are 20k stars on github, which is also a star project.

We often use canvas in our daily development, but its api will be very tired for dealing with complex business logic, so I share this article, hoping to help you.

Open source outposts share popular, interesting and practical open source projects on a daily basis. Participate in maintaining the open source technology resource library of 100000 + Star, including Python, Java, C/C + +, Go, JS, CSS, Node.js, PHP,. NET, etc.

Tags: Open Source

Posted on Sun, 24 Oct 2021 22:37:37 -0400 by elenev