绘制单个多边形
<template>
<div>
<div>
<button @click="onClear">清空</button>
</div>
<div>
<canvas
id="mycanvas"
ref="mycanvas"
width="700"
height="450"
@mousedown="canvasDown($event)"
@mousemove="canvasMove($event)"
@mouseup="canvasUp($event)"
@dblclick="doubleclick()"
>浏览器不持之canvas</canvas>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isdraw: false, //是否在画图形
ctx: null, //canvas对象
coordinates: [], //一个多边形的坐标信息
cor_index: 0, //当前多边形的索引
endtip: false //是否结束一个多边形的绘制
};
},
mounted() {
this.initDraw();
},
methods: {
initDraw() {
//初始化画布对象
const canvas = document.querySelector("#mycanvas");
this.ctx = canvas.getContext("2d"); //getContext() 方法返回一个用于在画布上绘图的环境,2d二维绘图
this.ctx.strokeStyle = "rgb(0, 195, 155)"; //图形边框颜色
},
// 清空
onClear() {
this.coordinates = [];
this.isdraw = false;
this.endtip = false;
this.ctx.clearRect(0, 0, 700, 450); //在给定的矩形内清除指定的像素
},
// 按下鼠标左键时--------------------------------------
canvasDown(e) {
console.log("点击");
var x = e.offsetX;
var y = e.offsetY;
//获取鼠标按下的坐标,放入数组中
this.coordinates.push({ cor_x: x, cor_y: y });
this.drawcircle();
this.isdraw = true; //正在画多边形
if (this.endtip) {
this.endtip = false; //清空,重新画
console.log("重新画");
}
console.log(this.coordinates);
},
// 鼠标移动时----------------------------------------------------------
canvasMove(e) {
//没开始画或者结束画之后不进行操作
if (this.coordinates.length == 0 || !this.isdraw || this.endtip) {
return;
}
var x = e.offsetX;
var y = e.offsetY;
//获取上一个点
var last_x = this.coordinates[this.coordinates.length - 1].cor_x;
var last_y = this.coordinates[this.coordinates.length - 1].cor_y;
this.ctx.clearRect(0, 0, 700, 450); //清空画布
this.drawline(); //把之前的点连线
this.drawcircle(); //画之前的点
//获取鼠标移动时的点,画线,实现线段跟踪效果。
this.ctx.beginPath();
this.ctx.moveTo(last_x, last_y);
this.ctx.lineTo(x, y); //追踪鼠标
this.ctx.stroke(); //绘制已定义的路径 追踪鼠标
// this.ctx.closePath();
},
// 释放鼠标按钮-------------------------------------------------
canvasUp(e) {},
// 双击按钮时---------------------------------------
doubleclick() {
console.log("双击");
//双击画布,在最后一个点的时候双击,自动连线第一个点,同时宣告画结束
var x0 = this.coordinates[0].cor_x;
var y0 = this.coordinates[0].cor_y;
var x1 = this.coordinates[this.coordinates.length - 1].cor_x;
var y1 = this.coordinates[this.coordinates.length - 1].cor_y;
this.ctx.beginPath();
this.ctx.moveTo(x0, y0);
this.ctx.lineTo(x1, y1);
this.ctx.stroke();
// this.ctx.closePath();
this.isdraw = false;
this.endtip = true;
this.coordinates.pop();
// this.drawcircle();
this.ctx.fillStyle = "rgba(0, 195, 155,0.4)";
var bx = this.coordinates[0].cor_x;
var by = this.coordinates[0].cor_y;
this.ctx.beginPath();
this.ctx.moveTo(bx, by);
for (var k = 1; k < this.coordinates.length; k++) {
var x = this.coordinates[k].cor_x;
var y = this.coordinates[k].cor_y;
this.ctx.lineTo(x, y);
}
this.ctx.fill();
// this.ctx.closePath();
console.log(this.coordinates);
this.coordinates = [];
},
//画线-把当前绘制的多边形之前的坐标线段绘制出来
drawline() {
for (var i = 0; i < this.coordinates.length - 1; i++) {
this.ctx.beginPath();
var x0 = this.coordinates[i].cor_x;
var y0 = this.coordinates[i].cor_y;
var x1 = this.coordinates[i + 1].cor_x;
var y1 = this.coordinates[i + 1].cor_y;
this.ctx.moveTo(x0, y0);
this.ctx.lineTo(x1, y1);
this.ctx.stroke();
// this.ctx.closePath();
}
},
//画点-把当前绘制的多边形之前的端点画圆
drawcircle() {
this.ctx.fillStyle = "rgb(0, 195, 155)";
for (var i = 0; i < this.coordinates.length; i++) {
var x = this.coordinates[i].cor_x;
var y = this.coordinates[i].cor_y;
this.ctx.beginPath(); //起始一条路径,或重置当前路径
this.ctx.moveTo(x, y); //把路径移动到画布中的指定点(x,y)开始坐标
this.ctx.arc(x, y, 5, 0, Math.PI * 2); //点
this.ctx.fill(); //填充点
// this.ctx.closePath();//创建从当前点回到起始点的路径
}
}
}
};
</script>
<style lang="scss" scoped>
.main {
height: 90vh;
color: black;
background: white;
}
#mycanvas {
border: 1px solid red;
position: fixed;
left: 0;
right: 0;
margin: auto;
}
</style>
绘制多个多边形 最终版本 包含判断线段交叉
<template>
<div>
<div>
<div v-for="(item,index) in all_coordinates" :key="index">
区域{{index+1}}
<el-input :maxlength="20" v-model="item.identify" placeholder="请输入区域名称" clearable></el-input>
</div>
<button @click="onClear">清空</button>
</div>
<div>
<canvas
id="mycanvas"
ref="mycanvas"
width="700"
height="450"
@mousedown="canvasDown($event)"
@mousemove="canvasMove($event)"
@mouseup="canvasUp($event)"
@dblclick="doubleclick()"
>浏览器不持之canvas</canvas>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isdraw: false, //是否在画图形
ctx: null, //canvas对象
coordinates: [], //一个多边形的坐标信息
cor_index: 0, //当前多边形的索引
endtip: false, //是否结束一个多边形的绘制
all_coordinates: [] //所有多边形的信息
};
},
mounted() {
this.initDraw();
},
methods: {
initDraw() {
//初始化画布对象
const canvas = document.querySelector("#mycanvas");
this.ctx = canvas.getContext("2d"); //getContext() 方法返回一个用于在画布上绘图的环境,2d二维绘图
this.ctx.strokeStyle = "rgb(0, 195, 155)"; //图形边框颜色
},
// 清空
onClear() {
this.all_coordinates = [];
this.coordinates = [];
this.isdraw = false;
this.endtip = false;
this.ctx.clearRect(0, 0, 700, 450); //在给定的矩形内清除指定的像素
},
// 按下鼠标左键时--------------------------------------
canvasDown(e) {
if (this.endtip) {
if (this.all_coordinates.length < 10) {
this.endtip = false; //清空,重新画
} else {
this.$message.warning("最多可绘制十个闭合的凸多边形区域");
return;
}
}
var x = e.offsetX;
var y = e.offsetY;
//获取鼠标按下的坐标,放入数组中
var insertFlag = true;
this.coordinates.forEach((item, index) => {
if (item.cor_x == x && item.cor_y == y) {
insertFlag = false;
}
});
if (insertFlag) {
this.coordinates.push({ cor_x: x, cor_y: y });
// 判断相交
var lineList = [];
this.coordinates.forEach((item, index) => {
if (index < this.coordinates.length - 1) {
lineList.push([
item.cor_x,
item.cor_y,
this.coordinates[index + 1].cor_x,
this.coordinates[index + 1].cor_y
]);
}
});
lineList.forEach((item, index) => {
if (index > 0 && index < lineList.length - 1) {
var flag = this.judgeIntersect(
lineList[lineList.length - 1][0],
lineList[lineList.length - 1][1],
lineList[lineList.length - 1][2],
lineList[lineList.length - 1][3],
lineList[index - 1][0],
lineList[index - 1][1],
lineList[index - 1][2],
lineList[index - 1][3]
);
if (flag) {
console.log("相交");
this.coordinates.pop();
}
}
});
}
if (this.coordinates.length > 19) {
this.$message.warning("每个区域最多可绘制20个点坐标");
this.doubleclick();
this.drawcircles();
return;
}
this.drawcircle();
this.isdraw = true; //正在画多边形
},
// 鼠标移动时----------------------------------------------------------
canvasMove(e) {
//没开始画或者结束画之后不进行操作
if (this.coordinates.length == 0 || !this.isdraw || this.endtip) {
return;
}
var x = e.offsetX;
var y = e.offsetY;
//获取上一个点
var last_x = this.coordinates[this.coordinates.length - 1].cor_x;
var last_y = this.coordinates[this.coordinates.length - 1].cor_y;
this.ctx.clearRect(0, 0, 700, 450); //清空画布
this.drawline(); //把之前的点连线
this.drawcircle(); //画之前的点
if (this.all_coordinates.length != 0) {
//不止一个多边形,把多边形们画出来
this.drawlines();
this.drawcircles();
this.fillarea();
}
//获取鼠标移动时的点,画线,实现线段跟踪效果。
this.ctx.beginPath();
this.ctx.moveTo(last_x, last_y);
this.ctx.lineTo(x, y); //追踪鼠标
this.ctx.stroke(); //绘制已定义的路径 追踪鼠标
this.ctx.closePath();
},
// 释放鼠标按钮-------------------------------------------------
canvasUp(e) {
this.ctx.clearRect(0, 0, 700, 450); //清空画布
this.drawline(); //把之前的点连线
this.drawcircle(); //画之前的点
if (this.all_coordinates.length != 0) {
//不止一个多边形,把多边形们画出来
this.drawlines();
this.drawcircles();
this.fillarea();
}
},
// 双击按钮时---------------------------------------
doubleclick() {
console.log("双击");
//双击画布,在最后一个点的时候双击,自动连线第一个点,同时宣告画结束
var x0 = this.coordinates[0].cor_x;
var y0 = this.coordinates[0].cor_y;
var x1 = this.coordinates[this.coordinates.length - 1].cor_x;
var y1 = this.coordinates[this.coordinates.length - 1].cor_y;
this.ctx.beginPath();
this.ctx.moveTo(x0, y0);
this.ctx.lineTo(x1, y1);
this.ctx.stroke();
this.ctx.closePath();
this.isdraw = false;
this.endtip = true;
// this.coordinates.pop();
this.all_coordinates.push(this.coordinates);
// this.drawcircle();
this.ctx.fillStyle = "rgba(0, 195, 155,0.4)";
var bx = this.coordinates[0].cor_x;
var by = this.coordinates[0].cor_y;
this.ctx.beginPath();
this.ctx.moveTo(bx, by);
for (var k = 1; k < this.coordinates.length; k++) {
var x = this.coordinates[k].cor_x;
var y = this.coordinates[k].cor_y;
this.ctx.lineTo(x, y);
}
this.ctx.fill();
this.ctx.closePath();
console.log(this.coordinates);
console.log(this.all_coordinates);
this.coordinates = [];
},
//画线-把当前绘制的多边形之前的坐标线段绘制出来
drawline() {
for (var i = 0; i < this.coordinates.length - 1; i++) {
this.ctx.beginPath();
var x0 = this.coordinates[i].cor_x;
var y0 = this.coordinates[i].cor_y;
var x1 = this.coordinates[i + 1].cor_x;
var y1 = this.coordinates[i + 1].cor_y;
this.ctx.moveTo(x0, y0);
this.ctx.lineTo(x1, y1);
this.ctx.stroke();
this.ctx.closePath();
}
},
//画点-把当前绘制的多边形之前的端点画圆
drawcircle() {
this.ctx.fillStyle = "rgb(0, 195, 155)";
for (var i = 0; i < this.coordinates.length; i++) {
var x = this.coordinates[i].cor_x;
var y = this.coordinates[i].cor_y;
this.ctx.beginPath(); //起始一条路径,或重置当前路径
this.ctx.moveTo(x, y); //把路径移动到画布中的指定点(x,y)开始坐标
this.ctx.arc(x, y, 5, 0, Math.PI * 2); //点
this.ctx.fill(); //填充点
this.ctx.closePath(); //创建从当前点回到起始点的路径
}
},
drawlines() {
//把所有多边形画出来
for (var i = 0; i < this.all_coordinates.length; i++) {
var cors = this.all_coordinates[i];
//前后坐标连线
for (var j = 0; j < cors.length - 1; j++) {
this.ctx.beginPath();
var x0 = cors[j].cor_x;
var y0 = cors[j].cor_y;
var x1 = cors[j + 1].cor_x;
var y1 = cors[j + 1].cor_y;
this.ctx.moveTo(x0, y0);
this.ctx.lineTo(x1, y1);
this.ctx.stroke();
this.ctx.closePath();
}
//最后一个与第一个连线
var begin_x = cors[0].cor_x;
var begin_y = cors[0].cor_y;
var end_x = cors[cors.length - 1].cor_x;
var end_y = cors[cors.length - 1].cor_y;
this.ctx.beginPath();
this.ctx.moveTo(begin_x, begin_y);
this.ctx.lineTo(end_x, end_y);
this.ctx.stroke();
this.ctx.closePath();
}
},
drawcircles() {
//为所有的多边形端点画圆
this.ctx.fillStyle = "rgb(0, 195, 155)";
for (var i = 0; i < this.all_coordinates.length; i++) {
var cors = this.all_coordinates[i];
for (var j = 0; j < cors.length; j++) {
var x = cors[j].cor_x;
var y = cors[j].cor_y;
this.ctx.beginPath();
this.ctx.moveTo(x, y);
this.ctx.arc(x, y, 5, 0, Math.PI * 2);
this.ctx.fill();
this.ctx.closePath();
}
}
},
// 颜色填充
fillarea() {
this.ctx.fillStyle = "rgba(0, 195, 155,0.4)";
for (var i = 0; i < this.all_coordinates.length; i++) {
var cors = this.all_coordinates[i];
var x0 = cors[0].cor_x;
var y0 = cors[0].cor_y;
this.ctx.beginPath();
this.ctx.moveTo(x0, y0);
for (var j = 1; j < cors.length; j++) {
var x = cors[j].cor_x;
var y = cors[j].cor_y;
this.ctx.lineTo(x, y);
}
this.ctx.fill();
this.ctx.closePath();
}
},
// 判断直线是否相交
judgeIntersect(x1, y1, x2, y2, x3, y3, x4, y4) {
if (
!(
Math.min(x1, x2) <= Math.max(x3, x4) &&
Math.min(y3, y4) <= Math.max(y1, y2) &&
Math.min(x3, x4) <= Math.max(x1, x2) &&
Math.min(y1, y2) <= Math.max(y3, y4)
)
)
return false;
var u, v, w, z;
u = (x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1);
v = (x4 - x1) * (y2 - y1) - (x2 - x1) * (y4 - y1);
w = (x1 - x3) * (y4 - y3) - (x4 - x3) * (y1 - y3);
z = (x2 - x3) * (y4 - y3) - (x4 - x3) * (y2 - y3);
return u * v <= 0.00000001 && w * z <= 0.00000001;
}
}
};
</script>
<style lang="scss" scoped>
.main {
height: 90vh;
color: black;
background: white;
}
#mycanvas {
border: 1px solid red;
position: fixed;
left: 0;
right: 0;
margin: auto;
}
</style>