Vue3 + TS中利用 canvas 创建绘画画板(签名板、画笔、矩形)
/ 画线段ctx.moveTo(startX, startY) // 画线起点ctx.lineTo(endX, endY) // 画线终点ctx.stroke() // 描绘线条// 定义鼠标初始点击的位置// 鼠标按下;painting = true // 将绘画状态改成true// 鼠标移动// 在鼠标移动的期间,获取鼠标的位置// 下面两行代码是更新线条的起点// 鼠标松开// 松开鼠标后
一、基础概念
1.1 Context:Canvas 的上下文、绘制环境,是所有绘制操作 api 的入口
const canvas = document.getElementById('canvas'); //获得画布
const ctx = canvas.getContext('2d'); // ctx 即 context
canvas
的getContext()
方法,返回的就是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
}
(未完)
更多推荐
所有评论(0)