关于javascript:每一个用到canvas的小伙伴都应该了解的fabricjs

5次阅读

共计 7270 个字符,预计需要花费 19 分钟才能阅读完成。

导语

这篇文章是承接上一篇我用 10000 张图片合成咱们美妙的霎时所做的 fabric 教学篇

好了, 开始咱们明天的正题:
咱们想在画布上画个根本的简略形态的时候,应用 Canvas 不会感觉有什么繁琐。但当画布上须要任何模式的互动,绘制简单的图形和在特定状况须要扭转图片的时候, 应用原生 canvas API 将会变得很艰难。
而 Fabric 旨在解决这个问题。

Fabric.js 是一个弱小而简略的 Javascript HTML5 画布库
Fabric 在画布元素之上提供交互式对象模型
Fabric 还具备 SVG-to-canvas(和 canvas-to-SVG)解析器

为了不便, 上面我将通过 vue 我的项目 为大家解说如何应用 Fabric

1. 装置

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

也能够在 官网 下载最新 js 文件, 通过 script 标签引入

2. 应用

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

2.1 绘制一个简略的图形

Fabric 提供了 7 种根底形态:

  • fabric.Circle (圆)
  • fabric.Ellipse (椭圆)
  • fabric.Line (线)
  • fabric.Polyline (多条线绘制成图形)
  • fabric.triangle (三角形)
  • fabric.Rect (矩形)
  • fabric.Polygon (多边形)
  • 矩形
// js

// 引入 fabric
import {fabric} from "fabric";

// 创立一个 fabric 实例
let canvas = new fabric.Canvas("canvas"); // 能够通过鼠标办法放大, 旋转
// or
// let canvas = new fabric.StaticCanvas("canvas");// 没有鼠标交互的 fabric 对象

// 创立一个矩形对象
let rect = new fabric.Rect({
    left: 200, // 间隔右边的间隔
    top: 200, // 间隔上边的间隔
    fill: "green", // 填充的色彩
    width: 200, // 矩形宽度
    height: 200, // 矩形高度
});

// 将矩形增加到 canvas 画布上
canvas.add(rect);

能够看到界面中填充了一个能够通过鼠标放大放大且能够旋转的绿色矩形
通过对象的模式配置元素款式, 十分的不便!

  • 圆形和三角形
// 创立一个圆形对象
let circle = new fabric.Circle({
    left: 0, // 间隔右边的间隔
    top: 0, // 间隔上边的间隔
    fill: "red", // 填充的色彩
    radius: 50, // 圆的半径
});
// 创立一个三角形对象
let triangle = new fabric.Triangle({
    left: 200, // 间隔右边的间隔
    top: 0, // 间隔上边的间隔
    fill: "blue", // 填充的色彩
    width: 100, // 宽度
    height: 100, // 高度
});
// 将图形形增加到 canvas 画布上
canvas.add(circle, triangle);

咱们能够通过以下属性设置, 决定是否能够对相干元素进行交互

canvas.selection = false; // 禁止所有选中
rect.set("selectable", false); // 只是禁止这个矩形选中

2.2 绘制图片

次要有通过 url 和 img 标签绘制两种形式

// 通过 url 绘制图片
fabric.Image.fromURL(// 本地图片须要通过 require 来引入,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);
    }
);
// 也能够通过标签绘制
let img = document.getElementById("img");
let image = new fabric.Image(img, {
    left: 100,
    top: 100,
    opacity: 0.8,
});
canvas.add(image);

2.3 通过自定义的门路绘制

在此之前咱们须要理解几个参数的含意

  • M :“move”挪动到某点
  • L :“line”画线 x,y
  • C :“curve”曲线
  • A :“arc”弧
  • z : 闭合门路(相似 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");

能够看到通过门路绘制, 咱们能够制作非常复杂的图形(然而个别用不到, 咱们个别用它来解析 SVG 后拿到 path 还原图形)

2.4 动画

第一个参数是动画的属性,第二个参数是动画的最终地位,第三个参数是一个可选的对象,指定动画的细节:持续时间,回调,动效等。

第三个参数次要有

  • duration 默认为 500ms。能够用来扭转动画的持续时间。
  • from 容许指定动画属性的起始值(如果咱们不心愿应用以后值)。
  • onComplete 动画完结之后的回调。
  • easing 动效函数。

2.4.1 相对动画

let canvas = new fabric.Canvas("canvas");
let rect = new fabric.Rect({
    left: 400, // 间隔右边的间隔
    top: 200, // 间隔上边的间隔
    fill: "green", // 填充的色彩
    width: 200, // 宽度
    height: 200, // 高度
});
rect.animate("left", 100, {onChange: canvas.renderAll.bind(canvas),
    duration: 1000,
});
canvas.add(rect);

2.4.2 绝对动画(第二个参数通过 +=,-= 等来决定动画的最终成果)

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,
});

2.4.3 定义动画的动效函数

默认状况下,动画应用“easeInSine”动效执行。如果这不是你须要的,fabric 为咱们提供了很多内置动画成果, fabric.util.ease 下有一大堆动效的选项。
罕用的有 easeOutBounce,easeInCubiceaseOutCubiceaseInElasticeaseOutElasticeaseInBounceeaseOutExpo

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

2.5 图像滤镜

目前 Fabric 为咱们提供了以下内置滤镜

  • BaseFilter 根本过滤器
  • Blur 含糊
  • Brightness 亮度
  • ColorMatrix 色彩矩阵
  • Contrast 比照
  • Convolute 卷积
  • Gamma 伽玛
  • Grayscale 灰度
  • HueRotation 色调旋转
  • Invert 倒置
  • Noise 乐音
  • Pixelate 像素化
  • RemoveColor 移除色彩
  • Resize 调整大小
  • Saturation 饱和

2.5.1 单个滤镜

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);
    // 增加滤镜
    img.filters.push(new fabric.Image.filters.Grayscale());
    // 图片加载实现之后,利用滤镜成果
    img.applyFilters();
    img.set({
        left: 300,
        top: 250,
    });
    canvas.add(img);
});

2.5.2 叠加滤镜

“filters”属性是一个数组,咱们能够用数组办法执行任何所需的操作:移除滤镜(pop,splice,shift),增加滤镜(push,unshift,splice),甚至能够组合多个滤镜。当咱们调用 applyFilters 时,“filters”数组中存在的任何滤镜将一一利用,所以让咱们尝试创立一个既色偏又亮堂(Brightness)的图像。

fabric.Image.fromURL(require("./aaa.jpeg"), (img) => {img.scale(0.5);
    // 增加滤镜
    img.filters.push(new fabric.Image.filters.Grayscale(),
        new fabric.Image.filters.Sepia(), // 色偏
        new fabric.Image.filters.Brightness({brightness: 0.2}) // 亮度
    );
    // 图片加载实现之后,利用滤镜成果
    img.applyFilters();
    img.set({
        left: 300,
        top: 250,
    });
    canvas.add(img);
});

能够看到多个滤镜的成果叠加显示了, 当然 Fabric 还反对自定义滤镜, 在本篇文章点赞过 500 后我将更新 fabric 高级篇, 感激大家的反对~

2.6 色彩

无论你是应用十六进制,RGB 或 RGBA 色彩,Fabric 都能解决的很好

2.6.1 定义色彩

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)");

2.6.2 色彩转换

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

咱们还能够用另一种色彩叠加,或将其转换为灰度版本。

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

2.7 突变

Fabric 通过 setGradient 办法反对突变,在所有对象上定义。调用 setGradient(‘fill’, { …})就像设置一个对象的“fill”值一样。

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

circle.setGradient("fill", {
    // 突变开始的地位
    x1: 0,
    y1: 0,
    // 突变完结的地位
    x2: circle.width,
    y2: 0,
    // 突变的色彩
    colorStops: {// 突变的范畴(0,0.1,0.3,0.5,0.75,1)0- 1 之间都能够
        0: "red",
        0.2: "orange",
        0.4: "yellow",
        0.6: "green",
        0.8: "blue",
        1: "purple"
    },
});

2.8 文本

fabric.Text 对象对于文本, 提供了比 canvas 更丰盛的性能,包含:

  • 反对多行 Multiline support 可怜的是,原生文本办法疏忽了新建一行。
  • 文本对齐 Text alignment 左,中,右。应用多行文本时很有用。
  • 文本背景 Text background 背景也反对文本对齐。
  • 文字装璜 Text decoration 下划线,上划线,贯通线。
  • 行高 Line Height 在应用多行文本时有用。
  • 字符间距 Char spacing 使文本更紧凑或更距离。
  • 子范畴 Subranges 将色彩和属性利用到文本对象的子对象中。
  • 多字节 Multibyte 反对表情符号。
  • 交互式画布编辑 On canvas editing 能够间接在画布上键入文本。
let text = new fabric.Text(
    "大家好~ 这里是前埔寨 \n 我是荣顶~\n 一个要成为开发王的男人!",
    {
        left: 0,
        top: 200,
        fontFamily: "Comic Sans", // 字体
        fontSize: 50, // 字号
        fontWeight: 800, // 字体粗细, 能够应用关键字(“normal”,“bold”)或数字(100,200,400,600,800)shadow: "green 3px 3px 2px", // 文字暗影, 色彩,程度偏移,垂直偏移和含糊大小。underline: true, // 下划线
        linethrough: true, // 删除线
        overline: true, // 上划线
        fontStyle: "italic", // 字体格调,normal(失常)或 italic(斜体)stroke: "#c3bfbf", // 描边的色彩
        strokeWidth: 1, // 描边的宽度
        textAlign: "center", // 文本对齐形式
        lineHeight: 1.5, // 行高
        textBackgroundColor: "#91A8D0", // 文本背景色彩
    }
);
canvas.add(text);

2.9 事件

fabric 中通过 on 办法来初始化事件,off 办法用来删除事件。

罕用的事件有以下

  • “mouse:down”鼠标被按下
  • “object:add”对象被增加
  • “after:render”渲染实现

还有一大堆:
鼠标事件:“mouse:down”,“mouse:move”和“mouse:up…”
抉择相干的事件:“before:selection:cleared”,“selection:created”,
具体的能够查看 官网文档

canvas.on("mouse:down", function(options) {canvas.clear();
    let text = new fabric.Text("你点我啦~", {
        left: 200,
        top: 200,
    });
    canvas.add(text);
    console.log(options.e.clientX, options.e.clientY);
});
canvas.on("mouse:up", function(options) {
    this.text = "你没点我 0.0";
    canvas.clear();
    let text = new fabric.Text("你没点我 0.0", {
        left: 200,
        top: 200,
    });
    canvas.add(text);
    console.log(options.e.clientX, options.e.clientY);
});

Fabric 容许将侦听器间接附加到 canvas 画布中的对象上。

let rect = new fabric.Rect({width: 100, height: 50, fill: "green"});
rect.on("selected", function() {console.log("哦吼~ 你抉择了我");
});

let circle = new fabric.Circle({radius: 75, fill: "blue"});
circle.on("selected", function() {console.log("哈哈哈~ 你抉择了我");
});

3.0 自在绘画

Fabric canvas 的 isDrawingMode 属性设置为 true 即可实现自在绘制模式.
这样画布上的点击和挪动就会被立即解释为铅笔或刷子。

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

最初

很开心写下这篇文章, 它是我用来总结演绎 fabric 的知识点并且十分用心的一篇文章, 心愿这篇文章对你有所帮忙, 目前 fabric 在国内还不是很火, 然而 github 上曾经有 19.2k 的 star 了, 也算是一个明星我的项目. 咱们日常开发常常会用到 canvas, 然而它的 api 对于解决简单的业务逻辑会令人感到十分的操劳, 所以我分享这篇文章, 心愿对大家有所帮忙, 点赞超过 500 我会更新 fabric.js 高级篇, 感激你的反对!

很快乐能够和大家一起变强!
关注我的公众号,前埔寨。我是荣顶,和我一起在键帽和字符上横跳,代码与程序中穿梭。🤞

正文完
 0