基于canvas画布的实用类Fabric.js的使用

目录

前言

一、Fabric.js简介

二、开始

1、引入Fabric.js

2、在main.js中使用

3、初始化画布

三、方法

四、事件

1、常用事件

2、事件绑定

3、事件解绑

五、canvas常用属性

六、对象属性

1、基本属性

2、扩展属性

七、图层层级操作

八、复制和粘贴

1、复制

2、粘贴

九、锁定

1、静止水平移动(lockMovementX)

2、静止垂直移动(lockMovementY)

3、静止旋转(lockRotation)

4、静止水平缩放(lockScalingX)

5、静止垂直缩放(lockScalingY)

6、限制拖动区域

十、分组

十一、动画

十二、图像滤镜

十三、渐变

1、线性渐变

2、径向渐变

十四、拖拽和缩放画布

1、拖拽画布

2、以画布中心点为基准手动缩放

3、以鼠标指针位置为基准缩放

十五、右键菜单删除

十六、自由绘画

1、开启绘图模式

2、关闭绘图模式

十七、绘制背景图片

1、方式一:通过img元素添加

2、方式二:通过图片路径添加

十八、绘制文本

1、基础用法

2、文本修饰

3、可编辑文本

十九、绘制线和路径

1、绘制直线

2、绘制虚线

3、绘制路径

二十、自由绘制矩形

二十一、自由绘制圆形

二十二、自由绘制椭圆形

二十三、自由绘制三角形

二十四、自由绘制多边形


前言

        演示Demo:前端可视化demo

        Demo源码:https://gitee.com/k21vin/front-end-data-visualization

        本文章所有的gif图片由于录屏软件问题,上面的鼠标位置都是错位显示的!!

一、Fabric.js简介

        Fabric.js是一个对canvas进行封装的Javascript库,在原生canvas之上提供了交互式对象模型,通过简洁的api就可以在画布上进行丰富的操作。

        它主要的功能包括在canvas上创建和填充图形,比如矩形、圆形、多边形;生成的图像自带缩放、旋转、拖拽等功能;还可以给图形填充渐变颜色;各个图形可以相互组合等等。

二、开始

1、引入Fabric.js

npm i fabric --save

2、在main.js中使用

// main.js
import fabric from "fabric"
Vue.use(fabric)

3、初始化画布



三、方法

canvas.add(object)                   // 添加对象
canvas.remove(object)                // 删除对象
canvas.setWidth(width)               // 设置canvas宽度
canvas.setHeight(height)             // 设置canvas高度
canvas.setDimensions({width, height})// 一键设置宽高
canvas.getObjects()                  // 获取所有对象
canvas.getActiveObject()             // 获取选中的对象
canvas.clear()                       // 清除画布中所有对象
canvas.renderAll()                   // 重绘
canvas.requestRenderAll()            // 请求重新渲染
canvas.getZoom()                     // 获取画布当前缩放值
canvas.sendToBack(object)            // 移到对象到最底层
canvas.viewportCenterObjectH(object) // 水平居中对象
canvas.viewportCenterObjectV(object) // 垂直居中对象
canvas.viewportCenterObject(object)  // 垂直水平居中对象
canvas.fxCenterObjectH(object)       // 动画水平居中对象
canvas.fxCenterObjectV(object)       // 动画垂直居中对象
canvas.fxCenterObject(object)        // 动画垂直水平居中对象

let canvasJsonData = JSON.stringify(canvas.toJSON()) // 将画布序列化成json数据
let canvasSvgData = canvas.toSVG() // 将画布序列化成svg数据
canvas.loadFromJSON(canvasJsonData)  // 反序列化Json数据

四、事件

1、常用事件

mouse: down         // 鼠标按下事件
mouse: move         // 鼠标移动事件
mouse: up           // 鼠标移动事件
mouse: over         // 鼠标移入事件
mouse: out          // 鼠标移出事件
mouse: dblclick     // 鼠标双击事件
object: added       // 对象被添加事件
object: removed     // 对象被删除事件
object: modified    // 对象被修改事件
object: rotating    // 对象被旋转事件
object: scaling     // 对象被缩放事件
object: moving      // 对象被移动事件

2、事件绑定

canvas.on('mouse: wheel', (opt) => {
  console.log(opt)
})

3、事件解绑

canvas.off('mouse: wheel')

五、canvas常用属性

canvas.selection = true                  // 画布是否可选中 默认为true、false:不可选中
canvas.selectionColor = 'transparent'    // 画布鼠标框选时的背景色
canvas.selectionBorderColor = 'transparent'// 画布鼠标框选时的边框颜色
canvas.selectionLineWidth = 6            // 画布鼠标框选时的边框厚度
canvas.selectionDashArray = [30, 4, 10] // 画布鼠标框选时边框虚线规则
canvas.selectionFullyContained = true   // 只选择完全包含在拖动选择矩形中的形状
canvas.backgroundColor = '#2E3136'      // 画布背景色
canvas.hoverCursor = 'pointer'          // 鼠标光标样式 default、pointer、move等
canvas.skipTargetFind = true            // 整个画板元素不能被选中
canvas.fireRightClick = true            // 启用右键,options.button的数字为3
canvas.stopContextMenu = true           // 禁止默认右键菜单

        Fabric.js 可以通过 viewportTransform 属性配置画布的视窗属性

canvas.viewportTransform[4] = 100
canvas.viewportTransform[5] = 100

        viewportTransform 是一个数组,里面有6个元素,默认值是 [1, 0, 0, 1, 0, 0]。从下标0开始,它们分别代表:

[0]: 水平缩放(x轴方向)
[1]: 水平倾斜(x轴方向)
[2]: 垂直倾斜(y轴方向)
[3]: 垂直缩放(y轴方向)
[4]: 水平移动(x轴方向)
[5]: 垂直移动(y轴方向)

六、对象属性

1、基本属性

let circle = new fabric.Circle({
  top: 100,    // y坐标
  left: 100,    // x坐标
  fill: '#17b978', // 填充色
  radius: 50  // 半径
})
rect.top = 100                       // y坐标
rect.left = 100                      // x坐标
rect.width = 100                     // 矩形宽度
rect.height = 100                    // 矩形高度
circle.radius = 50                   // 圆半径
rect.fill = '#17b978'                // 填充色
rect.stroke = '#FE5332'              // 线条颜色
rect.strokeWidth = 10                // 线条宽度
rect.strokeMiterLimit = index        // 可以用来记录当前选中的rectList列表的索引!!!!!

2、扩展属性

circle.set({
  hasBorders: false
}
circle.selectable = false                 // 控件不能被选择,不会被操作
circle.hasControls = false                // 只能移动不能(编辑)操作
circle.hasBorders = false                 // 选中时,是否显示边,true:显示(默认)
circle.borderColor = 'red'                // 选中时,边的颜色
circle.borderScaleFactor = 5              // 选中时,边的粗细
circle.borderDashArray = [20, 5, 10, 7]  // 选中时,虚线边的规则
circle.transparentCorners = false         // 选中时,角是否是空心 true:空心  false:实心
circle.cornerColor = "#a1de93",           // 选中时,角的颜色
circle.cornerStrokeColor = 'pink'         // 选中时,角的边框的颜色
circle.cornerStyle = 'circle'             // 选中时,角的属性  rect:矩形(默认)、circle:圆形
circle.cornerSize = 20                    // 选中时,角的大小为20
circle.cornerDashArray = [10, 2, 6]       // 选中时,虚线角的规则
circle.selectionBackgroundColor = '#ffc300' // 选中时,选框的背景色
circle.padding = 20                       // 选中时,选框离图形的距离
circle.borderOpacityWhenMoving = 0.6      // 当对象活动和移动时,对象控制边界的不透明度
triangle.perPixelTargetFind = true        // 选择三角形空白位置的时候无法选中,false:可以选中(默认)

七、图层层级操作

canvas.bringToFront(rect)    // 移到顶层
canvas.sendToBack(rect)      // 移到底层
canvas.bringForward(rect)    // 上移一层
canvas.sendBackwards(rect)   // 下移一层
canvas.moveTo(0)          // 移动到指定层

八、复制和粘贴

基于canvas画布的实用类Fabric.js的使用_第1张图片

1、复制

handleCopy() {
  if (!canvas.getActiveObject()) {
    this.$message.warning('请先选择元素')
    return
  }
  this.canvas.getActiveObject().clone(cloned => {
    this.cloneObjects = cloned
  })
}

2、粘贴

handlePaste() {
  if (!this.cloneObjects) {
    return this.$message.warning('还没复制过任何内容')
  }
  this.cloneObjects.clone(cloned => {
    this.canvas.discardActiveObject() // 取消选择
    // 设置新内容的坐标位置
    cloned.set({
      left: cloned.left + 10,
      top: cloned.top + 10,
      evented: true
    })
    if (cloned.type === 'activeSelection') { // 如果复制的是多个对象,则需要遍历克隆对象
      cloned.canvas = this.canvas;
      cloned.forEachObject(obj => {
        this.canvas.add(obj)
      })
      cloned.setCoords()
    } else {
      this.canvas.add(cloned)
    }
    this.cloneObjects.top += 10
    this.cloneObjects.left += 10
    this.canvas.setActiveObject(cloned)
    this.canvas.requestRenderAll()
  })
}

九、锁定

        Fabric对象可以添加一些属性进行锁定,例如静止水平移动、静止垂直移动,静止缩放等等

1、静止水平移动(lockMovementX)


let rect = new fabric.Rect({
  width: 100,
  height: 50,
  fill: '#ffde7d',
  top: 20,
  left: 20
})
rect.lockMovementX = true
canvas.add(rect)

2、静止垂直移动(lockMovementY)


let rect = new fabric.Rect({
  width: 100,
  height: 50,
  fill: '#ffde7d',
  top: 20,
  left: 20
})
rect.lockMovementY = true

3、静止旋转(lockRotation)


let rect = new fabric.Rect({
  width: 100,
  height: 50,
  fill: '#ff9a3c',
  top: 60,
  left: 160
})
rect.lockRotation = true

4、静止水平缩放(lockScalingX)


let rect = new fabric.Rect({
  width: 100,
  height: 50,
  fill: '#ffde7d',
  top: 20,
  left: 20
})
rect.lockScalingX = true

5、静止垂直缩放(lockScalingY)


let rect = new fabric.Rect({
  width: 100,
  height: 50,
  fill: '#f95959',
  top: 20,
  left: 20
})
rect.lockScalingY = true

6、限制拖动区域

基于canvas画布的实用类Fabric.js的使用_第2张图片


let boundingBox = new fabric.Rect({
  top: 100,
  left: 100,
  width: 600,
  height: 400,
  fill: '#f95959',
  selectable: false
})
let movingBox = new fabric.Rect({
  top: 150,
  left: 150,
  width: 100,
  height: 100,
  fill: 'yellow',
  hasBorders: false,
  hasControls: false,
  hoverCursor: 'move'
})
this.canvas.add(boundingBox);
this.canvas.add(movingBox);
this.canvas.on("object:moving", (opt) => {
  let top = movingBox.top;
  let left = movingBox.left;
  let topBound = boundingBox.top;
  let bottomBound = topBound + boundingBox.height;
  let leftBound = boundingBox.left;
  let rightBound = leftBound + boundingBox.width;
  opt.target.left = Math.min(Math.max(left, leftBound), rightBound - movingBox.width)
  opt.target.top = Math.min(Math.max(top, topBound), bottomBound - movingBox.height)
})

十、分组

        Groups是Fabric最强大的功能之一,它可以将任意数量的Fabric对象组合在一起,形成一个小组,分组后,所有对象都可以一起移动、修改、缩放、旋转甚至更改其外观等

基于canvas画布的实用类Fabric.js的使用_第3张图片


let group = new fabric.Group([circle, text], {
  left: 100,
  top: 100,
  angle: -10
})
canvas.add(group)

        修改分组的某个对象的属性:

基于canvas画布的实用类Fabric.js的使用_第4张图片


group.item(0).set("fill","red");
group.item(1).set({
  text:"trololo",
  fill:"white"
})

        分组时要记住的另一件事是对象的状态。例如,在与图像组成组时,需要确保这些图像已完全加载:

基于canvas画布的实用类Fabric.js的使用_第5张图片


fabric.Image.fromURL(logo, img => {
  let img1 = img.scale(0.3).set({left: 0, top: 0})

  fabric.Image.fromURL(logo, img => {
    let img2 = img.scale(0.3).set({left: 80, top: 0})

    fabric.Image.fromURL(logo, img => {
      let img3 = img.scale(0.3).set({left: 160, top: 0})
      
      let group = new fabric.Group([img1, img2, img3], {
        left: 10,
        top: 400
      })
      canvas.add(group)
    })
  })
})

十一、动画

        每个Fabric对象都有一个animate方法,该方法可以动画化该对象,animate(动画属性,动画的结束值,[动画的详细信息])

基于canvas画布的实用类Fabric.js的使用_第6张图片


let rect = new fabric.Rect({
  left: 100,
  top: 100,
  width: 100,
  height: 100,
  fill: 'red'
})
rect.animate("angle", 45, {
  onChange: canvas.renderAll.bind(canvas)
})
canvas.add(rect)

        第一个参数是要设置动画的属性。第二个参数是动画的结束值。如果矩形具有-15°的角度,并且我们传递了45,则动画将从-15°变为45°。第三个参数是一个可选对象,用于指定动画的详细信息-持续时间,回调,缓动等


rect.animate("angle", 45, {
  from: 0, // 允许指定可设置动画的属性的起始值(如果我们不希望使用当前值)
  duration: 1000, // 默认为500(ms),可用于更改动画的持续时间
  easing: fabric.util.ease.easeOutBounce, // 缓动功能 easeOutBounce、easeInCubic、easeOutCubic、easeInElastic、easeOutElastic、easeInBounce、easeOutExpo
  onChange: canvas.renderAll.bind(canvas), // 在每次刷新时都会执行
  onComplete: (e) => { console.log(e) } // 在动画结束时调用的回调
})

        animate的一个方便之处在于它还支持相对值

基于canvas画布的实用类Fabric.js的使用_第7张图片


// 向右移动100px
rect.animate('left', '+=100', {
  onChange: canvas.renderAll.bind(canvas)
})

// 逆时针旋转5度
rect.animate('angle', '-=5', {
  onChange: canvas.renderAll.bind(canvas)
})

十二、图像滤镜

        fabric.Image的每个实例都具有“ filters”属性,该属性是一个简单的过滤器数组。该阵列中的每个过滤器都是Fabric过滤器之一的实例。或您自己的自定义过滤器的实例。

基于canvas画布的实用类Fabric.js的使用_第8张图片


let url = 'http://localhost:82/public/img/5.png' // 图片url
let base64Url = await this.imgUrlToBase64(url) // 图片base64 url
// 正常照片
fabric.Image.fromURL(url, img => {
  img.scale(0.3)
  canvas.add(img)
})

// 单个滤镜
fabric.Image.fromURL(base64Url, img => {
  img.scale(0.3)
  img.left = 300
  // 添加滤镜
  img.filters.push(new fabric.Image.filters.Grayscale())
  // 图片加载完成之后,应用滤镜效果
  img.applyFilters()
  canvas.add(img)
})

// 叠加滤镜
fabric.Image.fromURL(base64Url, img => {
  img.scale(0.3)
  img.set({
    left: 300,
    top: 250,
  })
  img.filters.push(
    new fabric.Image.filters.Grayscale(),
    new fabric.Image.filters.Sepia(), //色偏
    new fabric.Image.filters.Brightness({ brightness: 0.2 }) //亮度
  )
  img.applyFilters()
  canvas.add(img)
})

        (说明:这里图片可能会出错,放本地图片地址会报“Cannot read property 'naturalWidth' of null”的错误,直接放网络图片地址会报“Failed to execute 'texImage2D' on 'WebGLRenderingContext': The image element contains cross-origin data, and may not be loaded.”的错误。解决方法就是将转为Base64格式

十三、渐变

        Fabric支持在所有对象上设置填充或描边属性的渐变,首先创建渐变,然后将其分配给填充或描边。

1、线性渐变

基于canvas画布的实用类Fabric.js的使用_第9张图片


// 圆
let circle = new fabric.Circle({
  left: 100,
  top: 100,
  radius: 50,
})
let gradient = new fabric.Gradient({
  type: 'linear', // linear or radial
  gradientUnits: 'pixels', // pixels or pencentage 像素 或者 百分比
  coords: { x1: 0, y1: 0, x2: circle1.width, y2: 0 }, // 至少2个坐标对(x1,y1和x2,y2)将定义渐变在对象上的扩展方式
  colorStops:[ // 定义渐变颜色的数组
    { offset: 0, color: 'red' },
    { offset: 0.2, color: 'orange' },
    { offset: 0.4, color: 'yellow' },
    { offset: 0.6, color: 'green' },
    { offset: 0.8, color: 'blue' },
    { offset: 1, color: 'purple' },
  ]
})
circle.set('fill', gradient);
canvas.add(circle)

2、径向渐变

基于canvas画布的实用类Fabric.js的使用_第10张图片


let circle = new fabric.Circle({
  left: 100,
  top: 100,
  radius: 50
})
let gradient = new fabric.Gradient({
  type: 'radial',
  coords: {
    r1: 50,
    r2: 0,
    x1: 50,
    y1: 50,
    x2: 50,
    y2: 50,
  },
  colorStops: [
    { offset: 0, color: '#fee140' },
    { offset: 1, color: '#fa709a' }
  ]
})
circle.set('fill', gradient);
canvas.add(circle)

十四、拖拽和缩放画布

1、拖拽画布


2、以画布中心点为基准手动缩放


3、以鼠标指针位置为基准缩放


this.canvas.on('mouse:wheel', this.onMouseWheel)

// 监听鼠标放大缩小事件
onMouseWheel(opt) {
  let delta = opt.e.deltaY // 滚轮,向上滚一下是 -100,向下滚一下是 100
  let zoom = this.canvas.getZoom() // 获取画布当前缩放值
  zoom *= 0.999 ** delta
  zoom = zoom > 10 ? 10 : (zoom < 0.1 ? 0.1 : zoom) // 最大放大10倍,最小缩小至10%
  this.canvas.zoomToPoint({ // 以鼠标指针位置为基准缩放
    x: opt.e.offsetX,
    y: opt.e.offsetY
  }, zoom)
  opt.e.preventDefault()
  opt.e.stopPropagation()
}

十五、右键菜单删除

基于canvas画布的实用类Fabric.js的使用_第11张图片



                    
                    

你可能感兴趣的:(fabric,vue.js,javascript,前端)