Fabric.js 入门

Fabric.js 入门

官网文档 fabricjs.com/docs/

操作API demo fabricjs.com/touch-event...

基础介绍

Fabric.js 是一个流行的 JavaScript HTML5 canvas 库,可以方便我们操作 canvas。

Fabric.js 是基于 DOM 和 BOM 开发的,所以最近写小程序,都不能使用 Fabric.js;都需要使用 webview

为什么使用Fabric.js

因为它提供了许多强大的功能和优点,推荐使用它有以下几个原因:

  1. 全面的功能: Fabric.js 提供了丰富的图形元素和工具,如矩形、椭圆、多边形、线条、文本等,并允许你在画布上灵活地操作它们。此外,它还支持各种变换和组合模式,如旋转、缩放、倾斜、编组等。
  2. 性能优化: Fabric.js 在处理大量对象或复杂图形时,能够提供良好的性能。它使用了一个高效的渲染引擎,能够智能地管理渲染缓存,并在需要时进行优化。
  3. 灵活性和可扩展性: Fabric.js 的设计非常灵活,可以通过继承和扩展现有的对象类来轻松地添加新的功能。此外,它还提供了各种事件(例如点击、触摸、双指缩放等),以方便与用户交互。
  4. 社区支持: Fabric.js 有一个活跃的社区,提供了大量的教程、示例和插件。这意味着当你遇到问题时,你很容易找到帮助和解决方案。
  5. 兼容性 Fabric.js 在各种浏览器上表现良好,包括现代移动设备。这意味着你可以在各种设备上使用 Fabric.js 来创建丰富的交互体验。

总结起来就一句话:Fabric.js 是目前社区内操作 canvas 的库里,使用人数和应用最多的库。而且比其他库体量都大很多

基本概念

  1. 画布(Canvas)

在 Fabric.js 中,画布是一个非常重要的元素。你可以将它看作是绘画的"画布",可以在上面绘制各种形状、图像和文本。Fabric.js 也提供了丰富的交互和动画功能。

  1. 对象(Object)

Fabric.js 提供了许多内置对象,如矩形、椭圆、线条、文本等,这些对象都有一些通用属性,如 lefttopwidthheight 等。同时,Fabric.js 也允许你创建自定义对象。

  1. 属性(Properties)

对象的属性定义了该对象的特点,比如颜色、大小、位置等。在 Fabric.js 中,你可以直接设置或修改对象的属性。

  1. 事件(Events)

Fabric.js 提供了丰富的事件模型,包括 mouse events,touch events,object events 等。你可以很容易地添加事件监听器到 Fabric.js 对象上,当特定事件发生时,你的回调函数会被调用。

  1. 变换(Transformations)

Fabric.js 提供了各种变换方法,如旋转(rotate())、缩放(scale())、倾斜(skewX()skewY())等。这些方法可以用来改变对象的位置、大小和形状。

  1. 组合(Composition)

在 Fabric.js 中,你可以创建复杂的图形组合。一个组合可以包含多个对象,这些对象会作为一个整体进行变换。

  1. 图层(Layers)

在 Fabric.js 中,你可以创建多个画布,并在这些画布上添加对象。这样,你可以轻松地管理复杂的图形层次结构,每个层次可以包含多个对象。

  1. SVG 支持

Fabric.js 还支持从 SVG 文件创建对象。这意味着你可以很容易地从 SVG 文件导入图形,然后在 Fabric.js 画布上进行操作。

Fabric.js对比原生canvas

Fabric.js 和原生canvas都是用于创建和操作图形的强大工具,但它们在某些方面有所不同。以下是使用这两种库创建矩形的基本示例。

使用 Fabric.js 创建矩形:

arduino 复制代码
// 引入 Fabric 库 
import fabric from 'fabric';
const canvas = new fabric.Canvas('c');
// 创建矩形对象
const rect = new fabric.Rect({
    left: 100,
    top: 100,
    fill: 'red',
    width: 200,
    height: 200
});
// 将矩形添加到画布上
canvas.add(rect);

使用原生 canvas 创建矩形:

ini 复制代码
// 获取页面中的canvas元素
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
ctx.moveTo(50, 50)
ctx.lineTo(200, 50)
ctx.lineTo(200, 120)
ctx.lineTo(50, 120)
ctx.lineTo(50, 50)
ctx.fillStyle = 'red'
ctx.fill()

这两段代码都会在 HTML 页面中创建一个红色的矩形,可以看出来 Fabric.js 的使用上更符合语义化,而且不用去换算每一笔画的位置等等繁琐过程

二、创建画布

绘制的开始最重要的是创建画布,下面以 react 为例;

javascript 复制代码
function Canvas() {
    const canvasRef = useRef(null);
    useEffect(() => {
        const canvas = new fabric.Canvas(canvasRef.current,
            {
                // ...【各种配置】
                fireRightClick: true, // 启用右键,button的数字为3
                stopContextMenu: true, // 禁止默认右键菜单
                controlsAboveOverlay: true, // 超出clipPath后仍然展示控制条
                preserveObjectStacking: true
             });
    }, []);
    return (
        <canvas ref={canvasRef} width={600} height={400}/>
    );
  }
  1. 使用 useRef 引入 canvas 标签,这样可以避免页面多个 canvas 时使用 id 造成冲突;
  2. 【各种配置】

fabricjs.com/docs/fabric...

Canvas 对象下的所有成员都可以加

  1. 设置 width 和 height(非常重要);如图是写在标签上固定的宽高。

项目中常用的是根据图片的宽高和页面视窗换算后再设置宽高;

宽高没设置,或者是设置错误会导致渲染问题。

scss 复制代码
canvasRef.current.setWidth(600)
canvasRef.current.setHeight(800)

三、绘制内容

往画布上绘制内容简单的说就两步,1. 绘制对象;2. 添加到画布

绘制对象

fabric.js 内置的对象有很多,这里简单举个例子;

php 复制代码
// 矩形
const rect = new fabric.Rect({
  left: 100,
  top: 100,
  fill: 'red',
  width: 200,
  height: 200
});
canvas.add(rect);

// 圆形
const circle = new fabric.Circle({
  left: 100,
  top: 100,
  fill: 'blue',
  radius: 100,
});
canvas.add(circle);

// 文本
const text = new fabric.Text('今晚吃鸡,大吉大利', {
  left: 100,
  top: 100,
  fill: 'black',
  fontSize: 30,
});
canvas.add(text);

文档左边目录这里都是可使用的对象,大家需要时自己查阅。

看上面的代码,绘制时比较重要的点位信息是 top, left, right, bottom, width, height

以图片画框为例:

基准点都是以图片的左上角为 0, 0

向右为 X 轴正方向

向下为 Y 轴正方向

一张图上的一个框,点位数据是四个点:左上角,右上角,右下角,左下角;

points:"x1,y1,x2,y2,x3,y3,x4,y4"

Top: y1; left: x1; Width: x2-x1; Height: y3-y2

这时直接画上去大概率是错误的!

原图的点位画在原图上才是正确的,在屏幕上显示时图片大概率不是原图尺寸;一定要进行缩放换算

比例就是显图和原图的比例。offsetWidth / imgOriginWidth

但是这里有两个坑

  1. 算出的 scale 不是画布对象上的 scaleX ,scaleY

scaleX 和 scaleY 表示的是当前对象在画布上的缩放,一开始画上去默认是 1;用户操作缩放后才出发改变,不要跟图片缩放搞混。

  1. 边框设置 strokeWidth 时, width 和 height 要减去一个 strokeWidth;

设置对象

scss 复制代码
getObjects()
getActiveObjects()
target.set({
    stroke: '#35A1F7',
    fill: 'rgba(53, 161, 247, 0.2)',
})

// canvas 可设置刷新机制,比如删除对象时更新画布;设置对象时并不会自动更新画布,执行 renderAll 更新
canvas.renderAll()

设置背景图

ini 复制代码
const imageElement = new Image();
    imageElement.setAttribute('crossOrigin', 'anonymous');
    imageElement.src = src;
    imageElement.onload = () => {
      const { width: imgOriginWidth, height: imgOriginHeight } = imageElement;
      // 计算缩放比例
      const { offsetWidth, offsetHeight } = boxDomRef.current;
      const scale_img_width = offsetWidth / imgOriginWidth; // 获取容器和图片的宽度比
      const scale_img_height = offsetHeight / imgOriginHeight; // 获取容器和图片的高度比
      // 如果图片的比例 高度大于最大高度 就以宽度的比例。
      const scale = imgOriginHeight * scale_img_width > offsetHeight ? scale_img_height : scale_img_width;
      canvasRef.current.scale = scale;
      // 图片实际在canvas上的宽高
      const imageWidth = imgOriginWidth * scale;
      const imageHeight = imgOriginHeight * scale;
      canvasRef.current.setWidth(offsetWidth);
      canvasRef.current.setHeight(offsetHeight);
      canvasRef.current.origin = imgData; // 将数据绑定到 canvas
      fabric.Image.fromURL(src, img => {
        // 是否居中 canvas 位置
        const config: any = { scaleX: scale, scaleY: scale, type: 'background' };
        if (centerX) {
          config.left = (offsetWidth - imageWidth) / 2;
        } else {
          config.left = 0;
        }
        if (centerY) {
          config.top = (offsetHeight - imageHeight) / 2;
        } else {
          config.top = 0;
        }
        img.set(config);
        // 2. 再画图
        canvasRef.current.setBackgroundImage(img, canvasRef.current.renderAll.bind(canvasRef.current));
      });
    };

绑定事件

未完待续

好用的API

fabricjs.com/docs/fabric... 原码文件

  1. _previousPointer

记录鼠标上一次点击的位置;

这样可以很方便的解决代码里,每次 mouseDown 时记录初始位置,太麻烦。

  1. vptCoords

获取画布偏移的位置

鼠标画框

首先 isDrawingMode 设置为 false,开启时是画笔,影响画框。

两种方式:

  1. 通过 selection 配合 mouse 事件
ini 复制代码
canvas.selection = true;
canvas.selectionColor = "transparent"; // 选框填充色:填充色:透明
canvas.selectionBorderColor = "#e11919"; // 选框边框颜色:红色
// 以上代码会在鼠标拖动时形成一个矩形框
// 然后再执行 mouse:up 事件时将矩形框添加至 canvas 上
  1. 只通过 mouse 事件
arduino 复制代码
通过 mouse:down;mouse:move;mouse:up 三个事件组合画框
相关推荐
光影少年4 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_5 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu10830189117 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾9 分钟前
前端基础-html-注册界面
前端·算法·html
Dragon Wu11 分钟前
前端 Canvas 绘画 总结
前端
CodeToGym15 分钟前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
~甲壳虫17 分钟前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫21 分钟前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js
Cwhat22 分钟前
前端性能优化2
前端
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js