Fabric.js 使用笔记

1,041 阅读6分钟

1.Fabric.js是什么?

Fabric.js 是一个可以简化 Canvas 程序编写的库。 Fabric.js 为 Canvas 提供所缺少的对象模型,svg parser,交互和一整套其他不可或缺的工具。

2.为什么要用Fabric.js?

Canvas 提供一个好的画布能力,但是 Api 不够友好。绘制简单图形其实还可以,不过做一些复杂的图形绘制,编写一些复杂的效果,就不是那么方便了。Fabric.js 就是为此而开发,它主要就是用对象的方式去编写代码。详细见中文文档

3.使用方式

    // 通过npm进行安装
    npm install fabric
    // 在.vue中引用
    import { fabric } from 'fabric'
    
    // 声名画布 xxx画布id  options初始化事件
    canvas = new fabric.Canvas('xxx', options);
    // 或者用 canvas 对对象属性进行修改
    canvs.isDrawingMode = true;
    
    // 使用 CDN
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.6.0/fabric.min.js"></script>
    
    // react中使用
    import React, { useEffect, useRef, useState } from 'react';
    import { fabric } from 'fabric';
 
    export default function App() {
      const canvasRef = useRef(null);
      const [canvas, setCanvas] = useState(null);
      return (
        <div>
          <canvas ref={canvasRef}></canvas>
        </div>
      );
    }

3.1 options对象属性

属性名类型注释
stopContextMenuBoolean禁止默认右键菜单
controlsAboveOverlayBoolean是否启用右键,右键默认button数字为3
fireRightClickBoolean超出clipPath后时候继续展示控制条
imageSmoothingEnabledBoolean解决文字导出后不清晰问题
isDrawingModeBoolean是否可以自由绘制(画笔)
selectableBoolean控制是否可选择/是否可操作
selectionBoolean时候显示画板被选中
skipTargetFindBoolean整个画板是否可被选中
freeDrawingBrushObject笔刷类型(SprayBrush:喷雾笔刷, circleBrush 圆形笔刷,texturePatternBrush 图案画笔, pencilBrush 铅笔笔刷默认)
setZoom(n:Number)function设置画板缩放比例
uniformScalingBoolean是否强制按比例缩放 默认true
uniScaleKeyString哪个键切换统一缩放
centeredScalingBoolean该参数定义是否启用或禁用居中缩放.默认false
ps:更多请查看文档
//图案画笔使用
let img = new Image();//创建图像
img.src ='xxxx.png'
//必须图片加载完毕才可下一步
img.onload = function(){
    // 创建图案画笔
    let texturePatternBrush = new fabric.PatternBrush(canvas)
    // 设置画笔的源指向图片
    texturePatternBrush.source = img
    // 使用图案画笔
    canvas.freeDrawingBrush = texturePatternBrush
}

// 普通画笔使用
canvas.freeDrawingBrush = circleBrush;

3.2 freeDrawingBrush(画笔)对象属性

//使用方式
canvas.freeDrawingBrush.width = "200"
属性名类型注释
colorString笔刷颜色设置
widthNumber设置画笔粗细
strokeLineCapString画笔结尾风格(roud, butt, square) 默认round
strokeLineJoinString画笔角落风格(miter, bevel, round) 默认round
strokeMiterLimitNumber笔刷最大的斜接长度
strokeDashArrayArray设置虚线(行程破折号数组)
shadowObject设置阴影
skipTargetFindBoolean整个画板是否可被选中
freeDrawingBrushobject笔刷工具属性设置
//设置阴影例子
canvas.freeDrawingBrush.shadow = new fabric.Shadow({
  blur: 10, // 羽化程度
  offsetX: 20, // x轴偏移量
  offsetY: 20, // y轴偏移量
  color: '#30e3ca' // 投影颜色
})

4.绘制图形

// 1.声名画布
let canvas= new fabric.Canvas('main');
// 2.设置矩形的属性
let options = {
    left:100,
    top:100,
    fill:'red',
    width:30,
    height:30
}
// 3. 绘制矩形
let rect = new fabric.Rect(options);
canvas.add(rect);

其他规则图形

  • 绘制矩形 let rect = new fabric.Rect
  • 绘制圆形 let circle = new fabric.Circle
  • 绘制三角形 let triangle = new fabric.Triangle

options属性

属性类型注释
leftNumber距离画布左侧的距离,单位是像素
topNumber距离画布上边的距离,单位是像素
fillString填充的颜色
widthNumber图形的宽度
heightNumber图形的高度
strokeWidthNumber描边宽度
strokeNumber描边颜色

绘制不规则图形

使用fabric.Path( ) 方法

// M 代表移动 M 0 0 则代表将画笔移动到 0,0坐标点
// L 代表线  L 200 100 从0,0 坐标画到 200,100坐标位置 
// Z 代表图形闭合路径
var path = new fabric.Path('M 0 0 L 200 100 L 170 200 z');
// set( )方法对三角形的位置、颜色、角度、透明度等属性进行设置。
path.set({ left: 120, top: 120,fill:'red' });
canvas.add(path); //添加进画布

使用fabric.Polygon 或者 fabric.Polyline

5.对图片的操作

 # html
 <input id="file" type="file" accept="image/* png/*"  onclick="changefile(event)" />
 # js
 function changefile(e){
        // 1.获取文件
        let file = res.target.files[0];
        // 2.转换成url 展示图片
        // 3.1 new FileReader()方法
        let reader = new FileReader();
            reader.onload = function (e) {
            imgurl.value = e.target.result;
            drawimg(e.target.result);
        }
        reader.readAsDataURL(file);
        // 3.2 window.URL.createObjectURL方法
        let url = window.URL.createObjectURL(file);
        drawImg(url);
 }
 
 function drawImg(file){
     if (!file) throw new Error('file is undefined');
    // 第一种
    // fabric.Image.fromURL(file,function(oImg){
    //     oImg.set("name",'图片')
    //     canvas.add(oImg);
    // })
    // 第二种
    const imgEl = document.createElement('img');
    imgEl.src = file;
    imgEl.onload = function (res) {
        console.log(res);
        const imgInstance = new fabric.Image(imgEl, {
            name: '图片',
            left: 0,
            top: 0,
        });
        // canvas.add(imgInstance);
        // 设置缩放
        canvas.add(imgInstance);
        canvas.setActiveObject(imgInstance);
        canvas.renderAll(); //重新渲染
        // 删除页面中的图片元素
        imgEl.remove();
    }
 }

6.插入SVG

6.1 插入svg元素

 // 获取文件 如图片插入那获取一致
 ........
 drawSvg(url)
 function drawSvg(url){
    if (!file) throw new Error('file is undefined');
    fabric.loadSVGFromURL(file, function (objects, options) {
        const obj = fabric.util.groupSVGElements(objects, options);
        canvas.add(obj).renderAll();
    });
 }

6.2 插入svg字符串

//textcont.value 获取textarea输入的值
function comitSvg() {
    if (textcont.value) {
        fabric.loadSVGFromString(textcont.value, function (obj, options) {
            let objs = fabric.util.groupSVGElements(obj, options);
            objs.set('id', getID(objs))
            objs.set('name', "路径")
            canvas.add(objs).renderAll();
            show1.value = false;
            textcont.value = '';
        })
    } else {
        alert("内容为空!");
    }
}

7 画布的交互

事件对象注释
mouse:down画布鼠标按下时
mouse:move画布鼠标移动时
mouse:up画布鼠标抬起时
after:render画布画布重绘后
object:selectedobject对象被选中
object:movingobject对象移动
object:rotatingobject对象被旋转
object:addedobject对象被加入
object:removedobject对象被移除
// 画布交互
let canvas = new Fabric.Canvas('canvas');
canvas.on('mouse:down',function(options){
    console.log(options)
})
// 画上上对象交互
let rect = new fabric.Rect({width:100,height:100,fill:'red'});
react.on("selected",function(options){
    alert("我被选中了")
})
canvas.add(rect).renderAll()

8.序列化与反序列化

8.1 序列化

let canvas = new fabric.Canvas('canvas');
let rect = new fabric.Rect({
    width: 100,
    height: 100,
    fill: 'red'
})
canvas.add(rect).renderAll()
console.log(JSON.stringify(canvas.toJSON()));

8.2 反序列化

let canvas = new fabric.Canvas('canvas');
canvas.loadFromJSON('{"objects":[{"type":"rect","left":50,"top":50,"width":20,"height":20,"fill":"green","overlayFill":null}
]}')

9.文本

9.1 Text普通文本

let text = new fabric.Text("hello farbic", { //文本属性
fontSize:30, // 字体大小
originX: 'center', // x轴方向对齐方向
originy: 'cennter', // y轴方向对齐方向
font:'' // 自定义字体
})
canvas.add(text).renderAll();

9.2Itext可动态编辑文本

     let text = new fabric.IText("hello world", {
        fontFamily: 'ubuntu',
        fontSize: 300,
        textAlign: "center",
    })
    text.setControlsVisibility({ //控制文本的手柄
        mt: false,
        mr: false,
        mb: false,
        ml: false
    });
    canvas.add(text);
    canvas.viewportCenterObject(text); // 画布中间
    canvas.setActiveObject(text); // 活跃状态
    text.enterEditing(); // 进入编辑状态
    text.selectAll(); // 选中所有的文本

9.3 导入自定义字体

例子:vue项目

  <style>
    @font-face {
      font-family: ali;
      src: url('../../fonts/AlibabaPuHuiTi-2-35-Thin.ttf');
    }
    @font-face {
      font-family: douyu;
      src: url('../../fonts/douyu.ttf');
    }
  </style>
  
  <script >
      import {fontaceobserver} from 'fontfaceobserver.js' //字体加载工具
      import {fabric} from 'fabric'
      const font = new FontFaceObserver('ali')
    const canvas = new fabric.Canvas('c')

    font.load()
      .then(() => {
        const iText = new fabric.IText('hello world', {
          fontFamily: 'ali'
        })

        canvas.add(iText)
      })

    function setFont(font) {
      let fontFamily = new FontFaceObserver(font)
      fontFamily.load()
        .then(() => {
          let target = canvas.getActiveObject()
          if (target) {
            target.set("fontFamily", font)
            canvas.requestRenderAll()
          }
        })
        .catch(() => {
          console.error('字体加载失败')
        })
    }
  </script>

10.笔记

10.1 方法

  1. add(object) 添加
  2. insertAt(object,index) 添加
  3. remove(object) 移除
  4. forEachObject 循环遍历
  5. getObjects() 获取所有对象
  6. item(int) 获取子项
  7. isEmpty() 判断是否空画板
  8. size() 画板元素个数
  9. contains(object) 查询是否包含某个元素
  10. fabric.util.cos cos函数
  11. fabric.util.sin sin函数
  12. fabric.util.drawDashedLine 绘制虚线
  13. getWidth() setWidth() 获取/设置宽度
  14. getHeight() 获取高度
  15. clear() 清空
  16. renderAll() 重绘
  17. requestRenderAll() 请求重新渲染
  18. rendercanvas() 重绘画板
  19. getCenter().top/left 获取中心坐标
  20. toDatalessJSON() 画板信息序列化成最小的json
  21. toJSON() 画板信息序列化成json
  22. moveTo(object,index) 移动
  23. dispose() 释放
  24. setCursor() 设置手势图标
  25. getSelectionContext()获取选中的context
  26. getSelectionElement()获取选中的元素
  27. getActiveObject() 获取选中的对象
  28. getActiveObjects() 获取选中的多个对象
  29. discardActiveObject()取消当前选中对象
  30. isType() 图片的类型
  31. setColor(color) = canvas.set("full",""); 填充颜色
  32. rotate() 设置旋转角度
  33. setCoords() 设置坐标
  34. setActiveObject() 对象被获取

10.2 事件

  1. object:added
  2. object:removed
  3. object:modified
  4. object:rotating
  5. object:scaling
  6. object:moving
  7. object:selected 这个方法v2已经废弃,使用selection:created替代,多选不会触发
  8. before:selection:cleared
  9. selection:cleared
  10. selection:updated
  11. selection:created
  12. path:created
  13. mouse:down
  14. mouse:move
  15. mouse:up
  16. mouse:over
  17. mouse:out
  18. mouse:dblclick