一、基础概念

1.1 Context:Canvas 的上下文、绘制环境,是所有绘制操作 api 的入口

const canvas = document.getElementById('canvas'); //获得画布
const ctx = canvas.getContext('2d'); // ctx 即 context

canvasgetContext()方法,返回的就是CanvasRenderingContext2D对象。

1.2 清除矩形(clearRect)

// 清除某个矩形内绘制的内容,相当于橡皮擦
ctx.clearRect(x, y, width, hegiht);

二、代码实例

所以在Vue3 + TS中我们这么定义数据,如下

(1)绘画板一定会用到鼠标点击、移动等事件,所以先定义事件

@mousedown 对应的是 鼠标按下事件

@mousemove 对应的是 鼠标移动事件

@mouseup 对应的是 鼠标弹起事件

注意:canvas不能用css单独设置width和height,原因自己查阅资料

(2)定义的数据

(3)onMounted钩子函数中,获取 canvas 操作的接口

(4)选择画笔(在选择前需要清空之前的数据)

(5)定义获取鼠标当前位置的函数

(6)清空画布

以下都是定义的公共方法

2.1 画笔的功能实现(比如签字墙)

画笔:当鼠标点下去之后可实现绘画线条的效果,在鼠标按下去的一瞬间,获取起点的坐标点,随后在鼠标移动的途中,获取下一个点,然后连在一起,就是两点形成一条直线。随后将新获取到的点当做起点,持续重复该操作,即可出现画线条的效果。

2.1.1 首先定义一个画线的函数方法(在另一篇博客里面可查)http://t.csdnimg.cn/HIP4F
// 画线段
const paint = (startX: number, startY: number, endX: number, endY: number, ctx: CanvasRenderingContext2D) => {
  ctx.beginPath()
  ctx.globalAlpha = 1
  ctx.lineWidth = 2
  ctx.strokeStyle = '#000'
  ctx.moveTo(startX, startY)  // 画线起点
  ctx.lineTo(endX, endY)   // 画线终点
  ctx.closePath()
  ctx.stroke()  // 描绘线条
}
2.1.2 定义鼠标按下、移动、抬起事件函数(MouseEvent 是鼠标事件类型)
// 定义鼠标初始点击的位置
let startX = 0
let startY = 0

// 鼠标按下
const mousedown = (event: MouseEvent) => {
  ;[startX, startY] = getOffset(event)
  painting = true  // 将绘画状态改成true
}

// 鼠标移动
const mousemove = (event: MouseEvent) => {
  if (painting) {
    // 在鼠标移动的期间,获取鼠标的位置
    const [endX, endY] = getOffset(event)
    paint(startX, startY, endX, endY, ctx)
    // 下面两行代码是更新线条的起点
    startX = endX
    startY = endY
  }
}

// 鼠标松开
const mouseup = (event: MouseEvent) => {
  // 松开鼠标后 禁止画线条
  if (painting) painting = false
}



2.2 多个矩形框功能的实现

矩形框:矩形的rect方法是需要 起点、长、宽等参数,所以在鼠标点击下去获取起点,利用一个数组变量 在移动的过程中存储移动过的坐标数据,当鼠标抬起的时候,即有最后一个点的坐标,这时候用最后一个坐标减去起点坐标即宽高,调用即可实现。

实现多个矩形框:为了能同时绘制出多个矩形,用一个数组存储每个矩形对象,每次松开鼠标后把当前的矩形对象存进数组的头部(因为每次绘制是按顺序从数组中取出矩形绘制,如果存进尾部后绘制的矩形就会被前面的矩形覆盖,所以这里用的是unshift而不是push),因为每次绘制都需要清空画布,所以每次在画布上绘制矩形时都要还原之前画布的状态

2.2.1 首先定义一个画矩形框的函数方法 (在另一篇博客里面可查)http://t.csdnimg.cn/HIP4F
// 画矩形
const drawRectangle = (startX: number, startY: number, endX: number, endY: number, ctx: CanvasRenderingContext2D) => {
  ctx.beginPath()
  ctx.globalAlpha = 0.3
  ctx.lineWidth = 2
  ctx.strokeStyle = '#000'
  ctx.rect(startX, startY, endX - startX, endY - startY)  // 查阅上述文档
  ctx.stroke()
}
2.2.2 定义鼠标按下、移动、抬起事件
// 定义鼠标初始点击的位置
let startX = 0
let startY = 0
// 鼠标按下
const mousedown = (event: MouseEvent) => {
  points = [] // 每一次画矩形的时候,都先将存下的位置清空
  ;[startX, startY] = getOffset(event)
  painting = true
}

// 鼠标移动
const mousemove = (event: MouseEvent) => {
  if (painting) {
    // 在鼠标移动的期间,获取鼠标的位置
    const [endX, endY] = getOffset(event)
    if (key === 1) {
      clearCanvas() // 因为是鼠标移动事件,所以每次移动都会产生一个矩形,首先清空在移动中产生的矩形
      // 调用之前存储的已经画过的矩形,重新遍历渲染
      rectList.forEach((item) => {
        drawRectangle(item.startX, item.startY, item.endX, item.endY, ctx)
      })
      // 将移动获取到的坐标点,全部存入数组中
      points.push({
        x: endX,
        y: endY,
      })
      // 渲染当前画的矩形
      drawRectangle(startX, startY, points[points.length - 1].x, points[points.length - 1].y, ctx)
    } else {
      paint(startX, startY, endX, endY, ctx)
      startX = endX
      startY = endY
    }
  }
}

// 鼠标松开
const mouseup = (event: MouseEvent) => {
  const [endX, endY] = getOffset(event)
  if (key === 1) {
    // 记录画的每一个矩形,且需用unshift方法
    rectList.unshift({
      startX,
      startY,
      endX,
      endY,
    })
  }
  if (painting) painting = false
}

(未完)

Logo

前往低代码交流专区

更多推荐