canvas实现画布白板功能

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

我:***

但是为了生活,我最终还是低头了!!!

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

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

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

kotlin 复制代码
//开始触摸/绘制
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:清除指定矩形区域内的内容,它会将指定区域的像素设置为透明,从而实现清空画布或擦除特定区域的效果

kotlin 复制代码
     //移动
    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 对象,其中包含了在指定区域内每个像素的颜色信息

kotlin 复制代码
 //用户手指离开屏幕保存此次操作
    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
    },

旋转:旋转后将新的像素重新绘制在画布中
drawImage:在画布上绘制图像
getImageData:获取画布上指定矩形区域内的像素数据

kotlin 复制代码
    //记录画布操作
    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
    },
kotlin 复制代码
    //点击旋转
    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将像素数据绘制到画布上

kotlin 复制代码
  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
    },

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

删除的功能:三层画布实现橡皮擦只能擦除画笔层、导入图片至画布、文本框拖拽至任意位置等等需求

相关推荐
PineappleCoder4 天前
SVG 适合静态图,Canvas 适合大数据?图表库的场景选择
前端·面试·canvas
德育处主任5 天前
p5.js 用 cylinder() 绘制 3D 圆柱体
前端·数据可视化·canvas
蛋蛋_dandan6 天前
Fabric.js从0到1实现图片框选功能
canvas
wayhome在哪8 天前
用 fabric.js 搞定电子签名拖拽合成图片
javascript·产品·canvas
德育处主任8 天前
p5.js 掌握圆锥体 cone
前端·数据可视化·canvas
德育处主任9 天前
p5.js 3D 形状 "预制工厂"——buildGeometry ()
前端·javascript·canvas
德育处主任11 天前
p5.js 3D盒子的基础用法
前端·数据可视化·canvas
掘金安东尼12 天前
2分钟创建一个“不依赖任何外部库”的粒子动画背景
前端·面试·canvas
百万蹄蹄向前冲12 天前
让AI写2D格斗游戏,坏了我成测试了
前端·canvas·trae
用户25191624271114 天前
Canvas之画图板
前端·javascript·canvas