vue+konva.js(未使用vue-konva)实现数据标注矩形和多边形功能
vue+konva.js(未使用vue-konva)实现数据标注矩形和多边形功能 矩形和多边形都可以移动调整,未编写删除功能。注释写的还需详细吧
·
前言
vue+konva.js(未使用vue-konva)实现数据标注矩形和多边形功能
矩形和多边形都可以移动调整,未编写删除功能。注释写的还需详细吧
一、矩形和多边形绘画
二、矩形和多边形重新调整
三、代码
<template>
<div>
<el-menu class="el-menu-demo" mode="horizontal" @select="handleSelect">
<template v-for="(item, i) in tools">
<el-menu-item :index="i.toString()">
<i class="el-icon-location"></i>
<span slot="title">{{ item.nameCN }}</span>
</el-menu-item>
</template>
</el-menu>
<div id="map" ref="map"></div>
</div>
</template>
<style>
#map {
background: #ddd;
overflow: hidden;
width: 100%;
aspect-ratio: 16/9;
}
</style>
<script>
import Konva from "konva";
export default {
name: "MyKonva",
data() {
return {
stage: null,
layer: null,
shape: null,
image: { src: require("@/assets/dog.jpeg") },
tools: [
{ id: 1, nameEN: "rect", nameCN: "矩形" },
{ id: 2, nameEN: "poly", nameCN: "多边形" },
],
currentTool: "",
drawing: false, //一开始不能绘画
currentDrawingShape: null, //现在绘画的图形
pointStart: [], //记录鼠标按下的起始坐标
polygonPoints: [], //存储绘画多边形各个顶点的数组
};
},
mounted() {
this.initKonvaStage();
},
methods: {
/**
*初始化konva舞台
*/
initKonvaStage() {
//1实例化stage层
this.stage = new Konva.Stage({
container: "map",
width: this.$refs.map.clientWidth,
height: this.$refs.map.clientHeight,
});
this.stage.container().style.cursor = "crosshair";
//2实例化layer层
this.layer = new Konva.Layer();
var imageObj = new Image();
//imageObj的this是imagedom对象,不是vc
var vc_this = this;
imageObj.onload = function () {
//3实例化shape层
vc_this.shape = new Konva.Image({
x: 0,
y: 0,
width: vc_this.stage.width(),
height: vc_this.stage.height(),
image: imageObj,
});
//4将layer层添加到stage层
vc_this.stage.add(vc_this.layer);
// 5将shape层添加到layer层
vc_this.layer.add(vc_this.shape);
};
imageObj.src = this.image.src;
//给***舞台***绑定事件
//鼠标按下
this.stage.on("mousedown", (e) => {
//图形起始点只能在图片层上,移除变形框
if (e.target === this.shape) {
// 如果有,就移除舞台上唯一一个的变形框
if (this.stage.find("Transformer").length != 0) {
this.stage.find("Transformer")[0].destroy();
}
//如果不在绘画且舞台上的多边形被选中
if (!this.drawing && this.stage.find("Circle").length != 0) {
var circlePoints = this.stage.find("Circle");
for (var i = 0; i < circlePoints.length; i++) {
if (circlePoints[i].visible()) {
//隐藏顶点
this.stage.find("Circle").forEach((element) => {
element.hide();
});
return;
}
}
}
this.layer.draw();
//开始初始绘画
this.stageMousedown(this.currentTool, e);
return;
}
//允许后续点绘画在其他图形上
if (this.drawing) {
this.stageMousedown(this.currentTool, e);
return;
}
});
//鼠标移动
this.stage.on("mousemove", (e) => {
if (this.currentTool && this.drawing) {
//绘画中
this.stageMousemove(this.currentTool, e);
}
});
//鼠标放开
this.stage.on("mouseup", (e) => {
this.stageMouseup(this.currentTool, e);
});
},
/**
* 圆形
* @param //x x坐标
* @param //y y坐标
*/
drawCircle(x, y) {
const circle = new Konva.Circle({
name: "circle",
x: x,
y: y,
radius: 5,
visible: true, //是否显示
fill: "#ffffff",
stroke: "#333333",
draggable: false,
strokeWidth: 0.5,
});
var vc_this = this;
var xChange, yChange;
this.layer.add(circle);
this.layer.draw();
circle.on("dragstart", (e) => {
var polyPoints = vc_this.currentDrawingShape
.getChildren((element) => {
return element.getClassName() === "Line";
})[0]
.points();
//查找拖拽了多边形的哪个点
for (var i = 0; i < polyPoints.length; i += 2) {
if (
circle.getAttr("x") == polyPoints[i] &&
circle.getAttr("y") == polyPoints[i + 1]
) {
xChange = i;
yChange = i + 1;
break;
}
}
});
circle.on("dragmove", (e) => {
//更改拖拽多边形点的位置
var polyPoints = vc_this.currentDrawingShape
.getChildren((element) => {
return element.getClassName() === "Line";
})[0]
.points();
/* e.evt.offsetX - vc_this.currentDrawingShape.getAttr('x') ---> 抵消拖动组的xy影响 */
polyPoints[xChange] =
e.evt.offsetX - vc_this.currentDrawingShape.getAttr("x");
polyPoints[yChange] =
e.evt.offsetY - vc_this.currentDrawingShape.getAttr("y");
vc_this.currentDrawingShape
.getChildren((element) => {
return element.getClassName() === "Line";
})[0]
.points(polyPoints);
});
return circle;
},
/**
* 矩形
* @param //x x坐标
* @param //y y坐标
* @param //w 宽
* @param //h 高
* @param //c 颜色
* @param //sw 该值大于0-表示空心矩形(描边宽),等于0-表示实心矩形*/
drawRect(x, y, w, h) {
const rect = new Konva.Rect({
name: "rect",
x: x,
y: y,
width: w,
height: h,
fill: "green",
stroke: "green",
strokeWidth: 1,
opacity: 0.3,
draggable: true,
strokeScaleEnabled: false,
});
this.currentDrawingShape = rect;
this.layer.add(rect);
this.layer.draw();
var vc_this = this;
rect.on("mouseenter", function () {
vc_this.stage.container().style.cursor = "move";
});
rect.on("mouseleave", function () {
vc_this.stage.container().style.cursor = "crosshair";
});
rect.on("mousedown", (e) => {
//如果不是正在绘画图形时,可以添加变形框
if (!vc_this.drawing) {
// 如果有,就移除舞台上唯一一个的transformer
if (vc_this.stage.find("Transformer").length != 0) {
vc_this.stage.find("Transformer")[0].destroy();
}
var tr = new Konva.Transformer({
anchorCornerRadius: 5,
rotateEnabled: false, //关闭旋转
node: rect,
keepRatio: false, //不等比缩放
enabledAnchors: [
"top-left",
"top-right",
"bottom-left",
"bottom-right",
],
borderDash: [3, 3],
});
vc_this.layer.add(tr);
tr.attachTo(e.target);
vc_this.layer.draw();
return;
}
//绘画图形时,不能被拖动
if (vc_this.drawing) {
rect.setAttr("draggable", false);
return;
}
});
},
/**
*多边形
* @param points 多边形绘画的各个顶点,类型数组
*/
drawPloygon(points) {
const poly = new Konva.Line({
name: "poly",
points: points,
fill: "red",
stroke: "red",
strokeWidth: 1,
draggable: false,
opacity: 0.3,
lineCap: "round",
lineJoin: "round",
closed: true,
strokeScaleEnabled: false,
});
this.currentDrawingShape = poly;
this.layer.add(poly);
this.layer.draw();
var vc_this = this;
poly.on("mouseenter", (e) => {
vc_this.stage.container().style.cursor = "move";
});
poly.on("mouseleave", (e) => {
vc_this.stage.container().style.cursor = "crosshair";
});
poly.on("mousedown", (e) => {
//如果不是正在绘画图形时,可以显示顶点
if (!vc_this.drawing) {
vc_this.stage.container().style.cursor = "move";
console.log("mousedown");
//设置现在绘画节点的对象为该多边形和顶点的组
vc_this.currentDrawingShape = poly.getParent();
//先隐藏全部顶点
vc_this.stage.find("Circle").forEach((element) => {
element.hide();
//解绑第一个红色顶点的事件
element.off("mousedown");
});
//显示现在操作多边形的原来的顶点
vc_this.currentDrawingShape
.getChildren((element) => {
return element.getClassName() === "Circle";
})
.forEach((element) => {
element.show();
element.setAttr("draggable", true);
});
// 如果要让顶点和多边形一起拖拽,必须设置,多边形不能被拖拽
poly.setAttr("draggable", false);
poly.getParent().setAttr("draggable", true);
//使所有顶点在顶层显示
vc_this.stage.find("Circle").forEach((element) => {
element.moveToTop();
});
vc_this.layer.draw();
} else {
//绘画时,鼠标移入多边形,设置组不可以拖动
vc_this.stage.container().style.cursor = "crosshair";
poly.getParent().setAttr("draggable", false);
}
});
poly.getParent().on("dragend", (e) => {
vc_this.stage.container().style.cursor = "crosshair";
poly.getParent().setAttr("draggable", false);
});
return poly;
},
/**
* 组件el-menu点击事件
* @param key 索引值
* @param keyPath
*/
handleSelect(key, keyPath) {
//设置当前工具
this.currentTool = this.tools[key].nameEN;
},
/**
* 在舞台上鼠标点下发生的事件
* @param currentTool 当前选择的工具
* @param e 传入的event对象
*/
stageMousedown(currentTool, e) {
switch (currentTool) {
case "rect":
//初始化矩形
var x = e.evt.offsetX,
y = e.evt.offsetY;
this.pointStart = [x, y];
this.drawRect(x, y, 0, 0);
break;
case "poly":
//如果数组长度小于2,初始化多边形和顶点,是它们成为一组,否则什么都不做
if (this.polygonPoints.length < 2) {
var x = e.evt.offsetX,
y = e.evt.offsetY;
//拖拽组
var group = new Konva.Group({
x: 0,
y: 0,
name: "pointsAndPoly",
draggable: false,
});
//添加多边形的点
group.add(this.addPoint(e));
//绘画多边形
this.polygonPoints = [x, y];
group.add(this.drawPloygon(this.polygonPoints));
//使所有顶点在顶层显示
this.stage.find("Circle").forEach((element) => {
element.moveToTop();
});
this.layer.add(group);
this.stage.draw();
} //多边形增加顶点
else {
var x = e.evt.offsetX,
y = e.evt.offsetY;
//group继续添加多边形的点
this.currentDrawingShape.getParent().add(this.addPoint(e));
this.polygonPoints.push(x);
this.polygonPoints.push(y);
//绘画多边形
this.currentDrawingShape.setAttr("points", this.polygonPoints);
//使所有顶点在顶层显示
this.stage.find("Circle").forEach((element) => {
element.moveToTop();
});
this.stage.draw();
}
break;
default:
break;
}
this.drawing = true;
},
/**
* 鼠标在舞台上移动事件
* @param currentTool 当前选择的工具
* @param e 传入的event对象
*/
stageMousemove(currentTool, e) {
switch (currentTool) {
case "rect":
//绘画矩形中
this.currentDrawingShape.setAttrs({
width: e.evt.offsetX - this.pointStart[0],
height: e.evt.offsetY - this.pointStart[1],
});
break;
case "poly":
//多边形初始化后,如果数组长度大于2,鼠标移动时,实时更新下一个点
if (this.polygonPoints.length >= 2) {
var x = e.evt.offsetX,
y = e.evt.offsetY;
var tempPoints = this.polygonPoints.concat();
tempPoints.push(x);
tempPoints.push(y);
this.currentDrawingShape.setAttr("points", tempPoints);
}
break;
default:
break;
}
this.layer.draw();
},
/**
* 鼠标在舞台上移动事件
* @param currentTool 当前选择的工具
* @param e 传入的event对象
*/
stageMouseup(currentTool, e) {
switch (currentTool) {
case "rect":
this.drawing = false;
break;
default:
break;
}
this.layer.draw();
},
/**
* 增加多边形顶点
* @param e 传入的event对象
*/
addPoint(e) {
if (this.polygonPoints.length == 0) {
var vc_this = this;
//将第一个点标红,并显示
return this.drawCircle(e.evt.offsetX, e.evt.offsetY)
.setAttrs({
fill: "red",
})
.show()
.on("mousedown", (e) => {
//点击第一个红点,绘画多边形结束
//绘画多边形
this.currentDrawingShape.setAttr("points", this.polygonPoints);
//结束绘画多边形封闭
// this.currentDrawingShape.setAttr('closed', true);
vc_this.drawing = false;
vc_this.polygonPoints = [];
//隐藏所有顶点
vc_this.stage.find("Circle").forEach((element) => {
element.hide();
});
//所有顶点变为白色
vc_this.stage.find("Circle").forEach((element) => {
element.setAttrs({
fill: "#ffffff",
});
});
//把现在的绘画对象更改为点和多边形合成的组
this.currentDrawingShape = this.currentDrawingShape.getParent();
});
} else {
//绘画点并显示
return this.drawCircle(e.evt.offsetX, e.evt.offsetY).show();
}
},
},
};
</script>
四,添加了其他功能和完善了代码。konva标注多边形矩形—demo2.0
https://blog.csdn.net/u011472784/article/details/126320562
源码下载
https://download.csdn.net/download/u011472784/85932065
更多推荐
已为社区贡献2条内容
所有评论(0)