canvas实现画布白板功能

hello~大家好我是小小前端-libei

产品经理:我要实现一个集画笔颜色选择器、橡皮擦、旋转,撤销,导入图片等功能的白板
我:***

产品提出要做个白板功能,对于我来说就有点挑战性了,因为之前并没有接触过canvas,在研究了几天后慢慢摸索

初始化画布

getContext:获取一个 2D 渲染上下文对象。这个上下文对象提供了一系列的绘图方法和属性,用于在画布上进行二维图形的绘制

     <canvas
        ref="canvas"
        id="canvas"
        :width="canvasHeight"
        :height="canvasHeight"
        :style="{ top: -(canvasHeight - canvasWidth) / 2 + 'px' }"
        @touchstart="touchstart"
        @touchmove="touchmove"
        @touchend="touchend"
      ></canvas>

当开始绘制时,计算出画笔开始和结束位置

//开始触摸/绘制
touchstart(e) {
  this.isDrawing = true
  this.startX = e.touches[0].clientX - this.canvas.offsetLeft
  this.startY = e.touches[0].clientY - this.canvas.offsetTop
},

移动期间,区分是画笔还是橡皮擦模式
如果是画笔模式,则调用以下方法完成画笔绘制效果

  • beginPath(): 开始创建路径
  • moveTo(x, y): 将当前点移动到指定的坐标位置
  • lineTo(x, y): 从当前点画一条直线到指定的坐标位置
  • stroke(): 绘制路径的边框

如果是橡皮擦模式,则使用clearRect清除区域像素
其实也可以使用画布背景色-一般是白色来达到视觉上擦除的效果,不过如果产品提出橡皮擦只能擦除画笔痕迹不能擦除其他的,那么这种视觉上的假性橡皮擦就不靠谱,这种情况就使用clearRect矩形擦除法
clearRect:清除指定矩形区域内的内容,它会将指定区域的像素设置为透明,从而实现清空画布或擦除特定区域的效果

     //移动
    touchmove(e) {
      let x = e.touches[0].clientX - this.canvas.offsetLeft//画笔开始x轴位置
      let y = e.touches[0].clientY - this.canvas.offsetTop//画笔开始y轴位置
      // 如果是橡皮擦模式
      if (this.isRubber) {
        this.ctx.clearRect(x - 10, y - 10, 16, 16)
        return
      }
      this.ctx = this.canvas.getContext('2d')
      if (!this.isDrawing) return
      this.ctx.beginPath()
      this.ctx.moveTo(this.startX, this.startY)
      this.ctx.lineTo(x, y)
      this.ctx.stroke()
      this.startX = x
      this.startY = y
      this.backFlag = true
    }

当用户手指离开屏幕时,记录画布上的操作
getImageData:获取指定矩形区域内的像素数据。它返回一个 ImageData 对象,其中包含了在指定区域内每个像素的颜色信息

 //用户手指离开屏幕保存此次操作
    touchend() {
      if (!this.backFlag) return
      const ctx = this.ctx.getImageData(
        0,
        0,
        this.canvas.width,
        this.canvas.height
      )
      this.canvasState.push({ctx})
      this.backFlag = false
    },
    //记录画布操作
    canvasOperations() {
      if (!this.backFlag) return
      const ctx = this.ctx.getImageData(
        0,
        0,
        this.canvas.width,
        this.canvas.height
      )
      this.canvasState.push({
        ctx 
      })
      this.backFlag = false
    },

 旋转:旋转后将新的像素重新绘制在画布中
 drawImage:在画布上绘制图像

    //点击旋转
    rotateImage() {
      this.rotate('canvas', 'ctx', 90)
      // 记录
      this.backFlag = true
      this.canvasOperations()
    },
    rotate(canvasName, ctx, angle) {
    const canvas = this.$refs[canvasName]
    const tempCanvas = document.createElement('canvas')
    const tempContext = tempCanvas.getContext('2d')
    tempCanvas.width = canvas.width
    tempCanvas.height = canvas.height
    // 旋转画布
    this[ctx].translate(canvas.width / 2, canvas.height / 2)
    this[ctx].rotate((angle * Math.PI) / 180)
    // 恢复之前的绘画内容
    this[ctx].drawImage(tempCanvas, -canvas.width / 2, -canvas.height / 2)
    // 恢复画布状态
    this[ctx].setTransform(1, 0, 0, 1, 0, 0)
    },
 

撤销:将记录每一步操作的数组删除最新一次的操作,使用putImageData将像素数据绘制到画布上

  revoke() {
      // 移除最后一个保存的状态
      this.canvasState.pop()
      let lastState = this.canvasState[this.canvasState.length - 1]
      //将图像重新放上画布
      if (this.canvasState.length > 0) {
        this.ctx.putImageData(lastState.ctx, 0, 0)
      } else {
        //清空画布
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      }
      this.backFlag = false
    },

这样简易版的白板就完成了,各位可借鉴思路,代码不一定完全能够实现,因为我在原本功能上删除了一些需求代码,导致代码不是很完整

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值