vue3绘制和回显多边形
参考了这个:https://blog.csdn.net/weixin_42178050/article/details/130012696
将其从vue2的语法改成了vue3,效果如下:
代码如下:
<template>
<div class="app-container">
<div class="d-flex j-center">
<el-container>
<el-main>
<!--用来和鼠标进行交互操作的canvas-->
<canvas
id="canvas"
ref="canRef"
width="600px"
height="600px"
@mousedown="canvasDown"
@mousemove="canvasMove"
></canvas>
<!--存储已生成的点线,避免被清空-->
<canvas id="canvasSave" ref="canSaveRef" width="600px" height="600px"></canvas>
</el-main>
<el-footer>
<el-button
id="deleteCanvas"
class="deleteCanvas"
type="primary"
@click="deleteCanvasClick"
>清空选区</el-button
>
</el-footer>
</el-container>
<!--canvas回显-->
<!-- <canvas class="shaped" id="quad"></canvas> -->
</div>
</div>
</template>
<script setup lang="ts">
const canRef = ref()
const ctx = ref()
const canSaveRef = ref()
const ctxSave = ref()
let pointX = null
let pointY = null
let oIndex = -1 //判断鼠标是否移动到起始点处,-1为否,1为是
let pointArr = [] //存放坐标的数组
//回显数据
const pointColorArr = [
{
color: '#f7b5c1',
houseName: '601单元',
ponitArr: [
{ x: 6, y: 134 },
{ x: 6, y: 201 },
{ x: 63, y: 202 },
{ x: 66, y: 129 },
{ x: 6, y: 134 },
],
},
{
color: '#bcf7d9',
houseName: '602单元',
ponitArr: [
{ x: 442, y: 403 },
{ x: 440, y: 347 },
{ x: 581, y: 347 },
{ x: 584, y: 568 },
{ x: 5, y: 566 },
{ x: 3, y: 401 },
{ x: 442, y: 403 },
],
},
]
onMounted(async () => {
//初始化画布对象
//canRef.value = document.getElementById('canvas')
canRef.value.width = 600
canRef.value.height = 600
ctx.value = canRef.value.getContext('2d')
// canSaveRef.value = document.getElementById('canvasSave')
canSaveRef.value.width = 600
canSaveRef.value.height = 600
ctxSave.value = canSaveRef.value.getContext('2d')
ctx.value.strokeStyle = 'rgba(102,168,255,1)' //线条颜色
ctx.value.lineWidth = 3 //线条粗细
ctxSave.value.strokeStyle = 'rgba(102,168,255,1)' //线条颜色
ctxSave.value.lineWidth = 2 //线条粗细
init()
})
//初始化回显
function init() {
pointColorArr.map(item => {
canvasFill(item.ponitArr, item.color, item.houseName)
})
}
/*点击画点*/
function canvasDown(e) {
if (e.offsetX || e.layerX) {
pointX = e.offsetX === undefined ? e.layerX : e.offsetX
pointY = e.offsetY === undefined ? e.layerY : e.offsetY
let piX, piY
if (oIndex > 0 && pointArr.length > 0) {
piX = pointArr[0].x
piY = pointArr[0].y
//画点
makearc(piX, piY, GetRandomNum(2, 2))
pointArr.push({ x: piX, y: piY })
canvasSave(pointArr) //保存点线同步到另一个canvas
saveCanvas() //生成画布
} else {
piX = pointX
piY = pointY
makearc(piX, piY, GetRandomNum(2, 2))
pointArr.push({ x: piX, y: piY })
canvasSave(pointArr) //保存点线同步到另一个canvas
}
}
}
// 鼠标移动事件
function canvasMove(e) {
if (e.offsetX || e.layerX) {
pointX = e.offsetX === undefined ? e.layerX : e.offsetX
pointY = e.offsetY === undefined ? e.layerY : e.offsetY
let piX, piY
/*清空画布*/
ctx.value.clearRect(0, 0, canRef.value.width, canRef.value.height)
/*鼠标下跟随的圆点*/
makearc(pointX, pointY, GetRandomNum(4, 4))
if (pointArr.length > 0) {
if (
pointX > pointArr[0].x - 15 &&
pointX < pointArr[0].x + 15 &&
pointY > pointArr[0].y - 15 &&
pointY < pointArr[0].y + 15
) {
if (pointArr.length > 1) {
piX = pointArr[0].x
piY = pointArr[0].y
ctx.value.clearRect(0, 0, canRef.value.width, canRef.value.height)
makearc(piX, piY, GetRandomNum(4, 4))
oIndex = 1
}
} else {
piX = pointX
piY = pointY
oIndex = -1
}
/*开始绘制*/
ctx.value.beginPath()
ctx.value.moveTo(pointArr[0].x, pointArr[0].y)
if (pointArr.length > 1) {
for (let i = 1; i < pointArr.length; i++) {
ctx.value.lineTo(pointArr[i].x, pointArr[i].y)
}
}
ctx.value.lineTo(piX, piY)
ctx.value.fillStyle = 'rgba(161,195,255,1)' //填充颜色
//ctx.value.fill() //填充
ctx.value.stroke() //绘制
}
}
}
// 存储已生成的点线
function canvasSave(pointArr) {
ctxSave.value.clearRect(0, 0, ctxSave.value.width, ctxSave.value.height)
ctxSave.value.beginPath()
if (pointArr.length > 1) {
ctxSave.value.moveTo(pointArr[0].x, pointArr[0].y)
for (let i = 1; i < pointArr.length; i++) {
ctxSave.value.lineTo(pointArr[i].x, pointArr[i].y)
ctxSave.value.fillStyle = 'rgba(161,195,255,0.2)' //填充颜色
//ctxSave.value.fill();
ctxSave.value.stroke() //绘制
}
ctxSave.value.closePath()
}
console.log('存储已生成的点线', pointArr)
//判断最后一个点重合则结束绘制
if (pointArr.length > 1) {
const { 0: a, [pointArr.length - 1]: b } = pointArr
if (a.x === b.x && a.y === b.y) {
console.log('结束绘制')
}
}
}
//回显canvas区域
function canvasFill(pointArr, color, houseName) {
ctxSave.value.clearRect(0, 0, ctxSave.value.width, ctxSave.value.height)
ctxSave.value.beginPath()
if (pointArr.length > 1) {
ctxSave.value.moveTo(pointArr[0].x, pointArr[0].y)
for (let i = 1; i < pointArr.length; i++) {
ctxSave.value.lineTo(pointArr[i].x, pointArr[i].y)
}
ctxSave.value.fillStyle = `${color}B3` //填充颜色 ${color}6B ${color}
ctxSave.value.fill()
ctxSave.value.stroke() //绘制
canvasText(houseName, pointArr[0])
}
}
//绘制文字
function canvasText(text, point) {
ctxSave.value.font = '30px Consolas' //字体样式的属性
ctxSave.value.textAlign = 'center' //设置文本对齐方式
ctxSave.value.textBaseline = 'middle' //文本基线
const textWidth = ctxSave.value.measureText(text).width
const canvasWidth = canRef.value.width
console.log('canvasWidth', canvasWidth)
ctxSave.value.fillStyle = 'red' //字体颜色
ctxSave.value.fillText(text, point.x + 70, point.y + 100) //绘制文字
ctxSave.value.arc(point.x, point.y, 3, 0, Math.PI * 2) //基准点
}
/*生成画布 结束绘画*/
function saveCanvas() {
ctx.value.clearRect(0, 0, canRef.value.width, canRef.value.height)
ctxSave.value.closePath() //结束路径状态,结束当前路径,如果是一个未封闭的图形,会自动将首尾相连封闭起来
ctxSave.value.fill() //填充
ctxSave.value.stroke() //绘制
pointArr = []
}
//清空选区
function deleteCanvasClick() {
ctx.value.clearRect(0, 0, canRef.value.width, canRef.value.height)
ctxSave.value.clearRect(0, 0, canSaveRef.value.width, canSaveRef.value.height)
pointArr = []
}
/*验证canvas画布是否为空函数*/
function isCanvasBlank(canvas) {
const blank = document.createElement('canvas') //创建一个空canvas对象
blank.width = canvas.width
blank.height = canvas.height
return canvas.toDataURL() === blank.toDataURL() //为空 返回true
}
/*canvas生成圆点*/
function GetRandomNum(Min, Max) {
const Range = Max - Min
const Rand = Math.random()
return Min + Math.round(Rand * Range)
}
function makearc(x, y, r) {
const color = 'rgba(102,168,255,1)'
const s = 0
const e = 180
ctx.value.clearRect(0, 0, 199, 202) //清空画布
ctx.value.beginPath()
ctx.value.fillStyle = color
ctx.value.arc(x, y, r, s, e)
ctx.value.fill()
}
</script>
<style lang="stylus" scoped>
canvas {
border: 1px solid #333;
display: block;
}
.deleteCanvas {
width: 100px;
margin-left2: 200px;
margin-top2: 650px;
}
#canvas {
position: absolute;
left: 200px;
top: 0;
z-index: 1;
cursor: crosshair;
}
#canvasSave {
position: absolute;
left: 200px;
top: 0;
}
#canvasSave {
background-image: url('../assets/office.png');
background-repeat: no-repeat;
background-size: 600px;
}
</style>