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

目录

一、基于canvas画布的实用类Fabric.js的使用Part.1

  • Fabric.js简介

  • 开始

  • 方法

  • 事件

  • canvas常用属性

  • 对象属性

  • 图层层级操作

  • 复制和粘贴

二、基于canvas画布的实用类Fabric.js的使用Part.2

  • 锁定

  • 拖拽和缩放画布

  • 分组

  • 动画

  • 图像滤镜

  • 渐变

  • 右键菜单删除

三、基于canvas画布的实用类Fabric.js的使用Part.3

  • 自由绘画

  • 绘制背景图片

  • 绘制文本

  • 绘制线和路径

  • 自由绘制矩形

  • 自由绘制圆形

  • 自由绘制椭圆形

  • 自由绘制三角形

  • 自由绘制多边形

一、自由绘画

1、开启绘图模式
let canvas = new fabric.Canvas('canvas', {
  isDrawingMode: true // 开启绘图模式
})
canvas.freeDrawingBrush.color = '#11999e' // 设置画笔颜色
canvas.freeDrawingBrush.width = 10 // 设置画笔粗细
canvas.freeDrawingBrush.shadow = new fabric.Shadow({ // 设置画笔投影
  blur: 10,
  offsetX: 10,
  offsetY: 10,
  affectStroke: true,
  color: '#30e3ca'
})
2、关闭绘图模式
canvas.isDrawingMode = false

二、绘制背景图片

1、方式一:通过img元素添加
<img src="@/assets/images/logo.png" id="logo">

let img = document.getElementById('logo')
img.onload = () => {
  let canvasImage = new fabric.Image(imgElement, {
    left: 100, // 距离画布左侧距离
    top: 100, // 距离画布顶部距离
    width: 200, // 图片宽度
    height: 200, // 图片高度
    angle: 50, // 旋转
    opacity: 1 // 透明度
  })
  canvas.add(canvasImage)
}
2、方式二:通过图片路径添加
let url = 'http://localhost:82/public/img/logo.png'
fabric.Image.fromURL(url, img => {
  let canvasImage = img.set({
    scaleX: 0.5,
    scaleY: 0.5
  })
  canvas.add(canvasImage)
}) 

三、绘制文本

Fabric也提供了文本的相关功能,Fabric文本允许以面向对象的方式处理文本,原生canvas方法,只允许在非常低的级别上填充或描边文本,通过实例化fabric.Text实例,我们就可以使用文本,就像我们将使用任何其他Fabric对象:移动它,缩放它,更改其属性等, 其次它提供比canvas给我们更丰富的功能,包括:

Multiline support   // 支持多行
Text alignment      // 文本对齐 Left、center、right
Text background     // 文本背景 背景也遵循文本对齐
Text decoration     // 文字装饰 下划线Underline、上划线overline、贯穿线strike-through
Line height         // 行高 使用多行文字时出错
Char spacing        // 字符间距 使文本更紧凑或间距更大
Subranges           // 子范围 将颜色和属性应用于文本对象的子范围
Multibyte           // 多字节 支持表情符号
On canvas editing   // 交互式画布编辑 可以直接在canvas上键入文本
1、基础用法
let text = new fabric.Text('Hello World!', {
  left: 40,
  top: 10,
  fontFamily: 'Comic Sans', // 字体
  fontSize: 60, // 字号
  fontWeight: 600, // 字体重量(粗细),normal、bold 或 数字(100、200、400、600、800)
  fontStyle: 'normal', // 字体风格 正常 normal 或 斜体 italic
  charSpacing: 100, // 字距
  fill: 'red', // 字体颜色
  cornerColor: 'pink', // 角的颜色(被选中时)
  angle: 30, // 旋转
  backgroundColor: '#ffd460', // 背景色
  borderColor: 'yellowGreen', // 边框颜色(被选中时)
  borderScaleFactor: 4, // 边框粗细(被选中时)
  borderDashArray: [10, 4, 20], // 创建边框虚线
  stroke: '#3f72af', // 文字描边颜色(蓝色)
  strokeWidth: 2, // 文字描边粗细
  textAlign: 'left', // 对齐方式:left 左对齐; right 右对齐; center 居中
  opacity: 0.8, // 不透明度
  // text: '雷猴', // 文字内容,会覆盖之前设置的值
  selectable: true, // 能否被选中,默认true
  shadow: 'rgba(0, 0, 0, 0.5) 5px 5px 5px', // 投影
})
canvas.add(text)
2、文本修饰
// 下划线
let underlineText = new fabric.Text("I am an undrline text", {
  underline: true
})
canvas.add(underlineText)

// 贯穿线
let strokeThroughText = new fabric.Text("I am a stroke-through text", {
  linethrough: true,
  top: 40
})
canvas.add(strokeThroughText)

// 上划线
let overlineText = new fabric.Text("I am overline text", {
  overline:true,
  top: 80
})
canvas.add(overlineText)
3、可编辑文本
let IText = new fabric.IText('雷猴啊,双击打几个字试下~', {
  fontFamily: 'Comic Sans'
})
canvas.add(IText)

四、绘制线和路径

1、绘制直线
let line = new fabric.Line([0, 100, 100, 100], {
  fill: 'green', // 填充色
  stroke: 'green', // 笔触颜色
  strokeWidth: 2, // 笔触宽度
});
canvas.add(line);
2、绘制虚线

在绘制直线的基础上添加属性strokeDashArray[a,b],表示每隔a个像素空b个像素。

let line = new fabric.Line([0, 100, 100, 100], {
  fill: 'green', // 填充色
  stroke: 'green', // 笔触颜色
  strokeWidth: 2, // 笔触宽度
  strokeDashArray:[3,1]
});
canvas.add(line);
3、绘制路径

Fabric.js使用 new fabric.Path 创建路径。

M:可以理解为新的起始点 x,y 坐标

L:每个折点的 x,y 坐标

z:自动闭合(自动把结束点和起始点连接起来)

let path = new fabric.Path('M 0 0 L 200 100 L 170 200 z')
path.set({
    top: 120, // 距离容器顶部距离 120px
    left: 120, // 距离容器左侧距离 120px
    fill: 'hotpink', // 填充 亮粉色
    opacity: 0.5, // 不透明度 50%
    stroke: 'black', // 描边颜色 黑色
    strokeWidth: 10 // 描边粗细 10px
})

上述代码第一行“M”代表“移动”命令,“M 0 0” 代表把画笔移动到(0, 0)点坐标。“L”代表“线”,“L 200 100 ”的意思是使用钢笔画一条线,从(0, 0)坐标画到(200, 100)坐标。“z” 代表让图形闭合路径。这样就画出了一个三角形。画好三角形后,我们可以用set( )方法对三角形的位置、颜色、角度、透明度等属性进行设置。

五、自由绘制矩形

<template>
  <div class="canvas-box" ref="canvasBox">
    <canvas id="canvas"></canvas>
    <el-button @click="handleActiveRect">绘制矩形</el-button>
  </div>
</template>
<script>
export default {
  name: 'PointerDetail',
  data () {
    return {
      canvas: null,
      lastPoint: null, // 上次鼠标点位坐标
      strokeColor: 'transparent', // 轮廓填充颜色
      isActiveRect: false, // 是否激活绘制矩形
      rectList: [] // 绘制的矩形列表
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    // 初始化
    init() {
      this.canvas = new fabric.Canvas('canvas', {
        width: this.$refs.canvasBox.offsetWidth,
        height: this.$refs.canvasBox.offsetHeight,
        backgroundColor: '#2E3136',
        selectionColor: 'transparent',
        selectionBorderColor: 'transparent',
        hoverCursor: 'default'
      })
      this.canvas.on('mouse:down', this.onMouseDown)
      this.canvas.on('mouse:up', this.onMouseUp)
      this.canvas.on('object:added', this.onObjectAdded)
    },
    // 监听鼠标按下事件
    onMouseDown(opt) {
      if (this.isActiveRect) {
        this.lastPoint = opt.absolutePointer || null
        this.strokeColor = '#00FF64'
      }
    },
    // 监听鼠标松开事件
    onMouseUp(opt) {
      if (this.isActiveRect) {
        this.drawRect(opt.absolutePointer)
      }
    },
    // 绘制完成元素事件
    onObjectAdded(opt) {
      let target = opt.target
      if (target.stroke === '#00FF64') {
        this.isActiveRect && this.rectList.push(target)
      }
    },
    // 绘制矩形
    drawRect(pointer) {
      if (!this.lastPoint || JSON.stringify(this.lastPoint) === JSON.stringify(pointer)) { // 点击事件,不生成矩形
        return
      }
      let top = Math.min(this.lastPoint.y, pointer.y)
      let left = Math.min(this.lastPoint.x, pointer.x)
      let width = Math.abs(this.lastPoint.x - pointer.x)
      let height = Math.abs(this.lastPoint.y - pointer.y)
      let rect = new fabric.Rect({ 
        top, 
        left,
        width,
        height,
        fill: 'transparent',
        stroke: this.strokeColor,
        selectable: false
      })
      this.canvas.add(rect)
      this.lastPoint = null
      this.strokeColor = 'transparent'
    },
    // 激活绘制矩形
    handleActiveRect() {
      this.isActiveRect = !this.isActiveRect
      if(this.isActiveRect) {
        this.canvas.selectionBorderColor = '#00FF64'
      }
    }
  }
}

六、自由绘制圆形

<template>
  <div class="canvas-box" ref="canvasBox">
    <canvas id="canvas"></canvas>
    <el-button @click="handleActiveCircle">绘制圆形</el-button>
  </div>
</template>
<script>
export default {
  name: 'PointerDetail',
  data () {
    return {
      canvas: null,
      canvasCircle: null,
      downPoint: null,
      strokeColor: 'transparent', // 轮廓填充颜色
      isActiveCircle: false, // 是否激活绘制圆形
      circleList: [] // 绘制的圆形列表
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    // 初始化
    init() {
      this.canvas = new fabric.Canvas('canvas', {
        width: this.$refs.canvasBox.offsetWidth,
        height: this.$refs.canvasBox.offsetHeight,
        backgroundColor: '#2E3136',
        selectionColor: 'transparent',
        selectionBorderColor: 'transparent',
        hoverCursor: 'default'
      })
      this.canvas.on('mouse:down', this.onMouseDown)
      this.canvas.on('mouse:move', this.onMouseMove)
      this.canvas.on('mouse:up', this.onMouseUp)
      this.canvas.on('object:added', this.onObjectAdded)
    },
    // 监听鼠标按下事件
    onMouseDown(opt) {
      if (this.isActiveCircle) {
        this.downPoint = opt.absolutePointer
        this.strokeColor = '#00FF64'
        this.canvasCircle = new fabric.Circle({
          top: this.downPoint.y,
          left: this.downPoint.x,
          radius: 0,
          fill: 'transparent',
          stroke: this.strokeColor,
          strokeWidth: 2,
          selectable: false,
        })
        this.canvas.add(this.canvasCircle)
      }
    },
    // 监听鼠标移动事件
    onMouseMove(opt) {
      if (this.isActiveCircle && this.canvasCircle) {
        let radius = Math.min(Math.abs(this.downPoint.x - opt.absolutePointer.x), Math.abs(this.downPoint.y - opt.absolutePointer.y)) / 2
        let top = opt.absolutePointer.y > this.downPoint.y ? this.downPoint.y : this.downPoint.y - radius * 2
        let left = opt.absolutePointer.x > this.downPoint.x ? this.downPoint.x :  this.downPoint.x - radius * 2
        this.canvasCircle.set('radius', radius)
        this.canvasCircle.set('top', top)
        this.canvasCircle.set('left', left)
        this.canvas.requestRenderAll()
      }
    },
    // 监听鼠标松开事件
    onMouseUp(opt) {
      if (this.isActiveCircle) {
        if (JSON.stringify(this.downPoint) === JSON.stringify(opt.absolutePointer)) {
          this.canvas.remove(this.canvasCircle)
        } else {
          if (this.canvasCircle){
            this.canvasCircle.set('stroke', this.strokeColor)
          }
        }
        this.canvasCircle = null
      }
    },
    // 绘制完成元素事件
    onObjectAdded(opt) {
      let target = opt.target
      if (target.stroke === '#00FF64') {
        this.isActiveCircle && this.circleList.push(target)
      }
    },
    // 激活绘制圆形
    handleActiveCircle() {
      this.isActiveCircle = !this.isActiveCircle
      if(this.isActiveCircle) {
        this.canvas.selectionBorderColor = '#00FF64'
      }
    }
  }
}

七、自由绘制椭圆形

<template>
  <div class="canvas-box" ref="canvasBox">
    <canvas id="canvas"></canvas>
    <el-button @click="handleActiveEllipse">绘制椭圆形</el-button>
  </div>
</template>
<script>
export default {
  name: 'PointerDetail',
  data () {
    return {
      canvas: null,
      canvasEllipse: null,
      downPoint: null,
      strokeColor: 'transparent', // 轮廓填充颜色
      isActiveEllipse: false, // 是否激活绘制椭圆形
      ellipseList: [] // 绘制的椭圆形列表
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    // 初始化
    init() {
      this.canvas = new fabric.Canvas('canvas', {
        width: this.$refs.canvasBox.offsetWidth,
        height: this.$refs.canvasBox.offsetHeight,
        backgroundColor: '#2E3136',
        selectionColor: 'transparent',
        selectionBorderColor: 'transparent',
        hoverCursor: 'default'
      })
      this.canvas.on('mouse:down', this.onMouseDown)
      this.canvas.on('mouse:move', this.onMouseMove)
      this.canvas.on('mouse:up', this.onMouseUp)
      this.canvas.on('object:added', this.onObjectAdded)
    },
    // 监听鼠标按下事件
    onMouseDown(opt) {
      if (this.isActiveEllipse) {
        this.downPoint = opt.absolutePointer
        this.strokeColor = '#00FF64'
        this.canvasEllipse = new fabric.Ellipse({
          top: this.downPoint.y,
          left: this.downPoint.x,
          rx: 0,
          ry: 0,
          fill: 'transparent',
          stroke: this.strokeColor,
          strokeWidth: 2,
          selectable: false,
        })
        this.canvas.add(this.canvasEllipse)
      }
    },
    // 监听鼠标移动事件
    onMouseMove(opt) {
      if (this.isActiveEllipse && this.canvasEllipse) {
        let rx = Math.abs(this.downPoint.x - opt.absolutePointer.x) / 2
        let ry = Math.abs(this.downPoint.y - opt.absolutePointer.y) / 2
        let top = opt.absolutePointer.y > this.downPoint.y ? this.downPoint.y : this.downPoint.y - ry * 2
        let left = opt.absolutePointer.x > this.downPoint.x ? this.downPoint.x :  this.downPoint.x - rx * 2
        this.canvasEllipse.set('rx', rx)
        this.canvasEllipse.set('ry', ry)
        this.canvasEllipse.set('top', top)
        this.canvasEllipse.set('left', left)
        this.canvas.requestRenderAll()
      }
    },
    // 监听鼠标松开事件
    onMouseUp(opt) {
      if (this.isActiveEllipse) {
        if (JSON.stringify(this.downPoint) === JSON.stringify(opt.absolutePointer)) {
          this.canvas.remove(this.canvasEllipse)
        } else {
          if (this.canvasEllipse){
            this.canvasEllipse.set('stroke', this.strokeColor)
          }
        }
        this.canvasEllipse = null
      }
    },
    // 绘制完成元素事件
    onObjectAdded(opt) {
      let target = opt.target
      if (target.stroke === '#00FF64') {
        this.isActiveEllipse && this.ellipseList.push(target)
      }
    },
    // 激活绘制椭圆形
    handleActiveEllipse() {
      this.isActiveEllipse = !this.isActiveEllipse
      if(this.isActiveEllipse) {
        this.canvas.selectionBorderColor = '#00FF64'
      }
    }
  }
}

八、自由绘制三角形

<template>
  <div class="canvas-box" ref="canvasBox">
    <canvas id="canvas"></canvas>
    <el-button @click="handleActiveTriangle">绘制三角形</el-button>
  </div>
</template>
<script>
export default {
  name: 'PointerDetail',
  data () {
    return {
      canvas: null,
      canvasTriangle: null,
      downPoint: null,
      strokeColor: 'transparent', // 轮廓填充颜色
      isActiveTriangle: false, // 是否激活绘制三角形
      triangleList: [] // 绘制的三角形列表
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    // 初始化
    init() {
      this.canvas = new fabric.Canvas('canvas', {
        width: this.$refs.canvasBox.offsetWidth,
        height: this.$refs.canvasBox.offsetHeight,
        backgroundColor: '#2E3136',
        selectionColor: 'transparent',
        selectionBorderColor: 'transparent',
        hoverCursor: 'default'
      })
      this.canvas.on('mouse:down', this.onMouseDown)
      this.canvas.on('mouse:move', this.onMouseMove)
      this.canvas.on('mouse:up', this.onMouseUp)
      this.canvas.on('object:added', this.onObjectAdded)
    },
    // 监听鼠标按下事件
    onMouseDown(opt) {
      if (this.isActiveTriangle) {
        this.downPoint = opt.absolutePointer
        this.strokeColor = '#00FF64'
        this.canvasTriangle = new fabric.Triangle({
          top: this.downPoint.y,
          left: this.downPoint.x,
          width: 0,
          height: 0,
          fill: 'transparent',
          stroke: this.strokeColor,
          strokeWidth: 2,
          selectable: false,
        })
        this.canvas.add(this.canvasTriangle)
      }
    },
    // 监听鼠标移动事件
    onMouseMove(opt) {
      if (this.isActiveTriangle && this.canvasTriangle) {
        let width = Math.abs(this.downPoint.x - opt.absolutePointer.x)
        let height = Math.abs(this.downPoint.y - opt.absolutePointer.y)
        let top = opt.absolutePointer.y > this.downPoint.y ? this.downPoint.y : opt.absolutePointer.y
        let left = opt.absolutePointer.x > this.downPoint.x ? this.downPoint.x : opt.absolutePointer.x
        this.canvasTriangle.set('width', width)
        this.canvasTriangle.set('height', height)
        this.canvasTriangle.set('top', top)
        this.canvasTriangle.set('left', left)
        this.canvas.requestRenderAll()
      }
    },
    // 监听鼠标松开事件
    onMouseUp(opt) {
      if (this.isActiveTriangle) {
        if (JSON.stringify(this.downPoint) === JSON.stringify(opt.absolutePointer)) {
          this.canvas.remove(this.canvasTriangle)
        } else {
          if (this.canvasTriangle){
            this.canvasTriangle.set('stroke', this.strokeColor)
          }
        }
        this.canvasTriangle = null
      }
    },
    // 绘制完成元素事件
    onObjectAdded(opt) {
      let target = opt.target
      if (target.stroke === '#00FF64') {
        this.isActiveTriangle && this.triangleList.push(target)
      }
    },
    // 激活绘制矩形
    handleActiveTriangle() {
      this.isActiveTriangle = !this.isActiveTriangle
      if(this.isActiveTriangle) {
        this.canvas.selectionBorderColor = '#00FF64'
      }
    }
  }
}

九、自由绘制多边形

<template>
  <div class="canvas-box" ref="canvasBox">
    <canvas id="canvas"></canvas>
    <el-button @click="handleActivePolygon">绘制多边形</el-button>
  </div>
</template>
<script>
export default {
  name: 'PointerDetail',
  data () {
    return {
      canvas: null,
      canvasPolygon: null,
      strokeColor: 'transparent', // 轮廓填充颜色
      isActivePolygon: false, // 是否激活绘制多边形
      polygonList: [] // 绘制的多边形列表
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    // 初始化
    init() {
      this.canvas = new fabric.Canvas('canvas', {
        width: this.$refs.canvasBox.offsetWidth,
        height: this.$refs.canvasBox.offsetHeight,
        backgroundColor: '#2E3136',
        selectionColor: 'transparent',
        selectionBorderColor: 'transparent',
        hoverCursor: 'default'
      })
      this.canvas.on('mouse:down', this.onMouseDown)
      this.canvas.on('mouse:move', this.onMouseMove)
      this.canvas.on('mouse:dblclick', this.onDblclick)
      this.canvas.on('object:added', this.onObjectAdded)
    },
    // 监听鼠标按下事件
    onMouseDown(opt) {
      if (this.isActivePolygon) {
        this.strokeColor = '#00FF64'
        if (this.canvasPolygon === null) {
          this.createPolygon(opt)
        } else {
          this.changeCurrentPolygon(opt)
        }
      }
    },
    // 监听鼠标移动事件
    onMouseMove(opt) {
      if (this.isActivePolygon && this.canvasPolygon) {
        this.changePolygonBelt(opt)
      }
    },
    // 鼠标双击事件
    onDblclick(opt) {
      this.finishPolygon(opt)
    },
    // 绘制完成元素事件
    onObjectAdded(opt) {
      let target = opt.target
      if (target.stroke === '#00FF64') {
        this.isActivePolygon && this.polygonList.push(target)
      }
    },
    // 创建多边形
    createPolygon(opt) {
      this.canvasPolygon = new fabric.Polygon([
          { x: opt.absolutePointer.x, y: opt.absolutePointer.y },
          { x: opt.absolutePointer.x, y: opt.absolutePointer.y }
        ], {
          fill: 'transparent',
          stroke: this.strokeColor,
          objectCaching: false
      })
      this.canvas.add(this.canvasPolygon)
    },
    // 修改当前正在创建的多边形
    changeCurrentPolygon(opt) {
      let points = this.canvasPolygon.points
      points.push({
        x: opt.absolutePointer.x,
        y: opt.absolutePointer.y
      })
      this.canvas.requestRenderAll()
    },
    // 多边形橡皮带
    changePolygonBelt(opt) {
      let points = this.canvasPolygon.points
      points[points.length - 1].x = opt.absolutePointer.x
      points[points.length - 1].y = opt.absolutePointer.y
      this.canvas.requestRenderAll()
    },
    // 完成多边形绘制
    finishPolygon(opt) {
      let points = this.canvasPolygon.points
      points[points.length - 1].x = opt.absolutePointer.x
      points[points.length - 1].y = opt.absolutePointer.y
      points.pop()
      points.pop()
      this.canvas.remove(this.canvasPolygon)
      if (points.length > 2) {
        let polygon = new fabric.Polygon(points, {
          stroke: this.strokeColor,
          fill: 'transparent',
          selectable: false
        })
        this.canvas.add(polygon)
      } else {
        this.$message.warning('标记框小于最小标定像素!')
      }
      this.canvasPolygon = null
      this.canvas.requestRenderAll()
      this.strokeColor = 'transparent'
    },
    // 激活绘制多边形
    handleActivePolygon() {
      this.isActivePolygon = !this.isActivePolygon
      if(this.isActivePolygon) {
        this.canvas.selectionBorderColor = '#00FF64'
      }
    }
  }
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值