包含的功能
-
图片渲染
-
矩形绘制,矩形渲染
-
图形的删除(通过id)
-
文字的渲染, 文字位置更新
-
矩形的变换(使矩形可以拖动,放大,缩小,通过拖动下图的点来实现图形变换),移除矩形变换函数
-
最后面添加了点击绘制线段和多边形的函数,需要的可自行添加到类里面
-
图片放大缩小
-
矩形框的高亮
-
类的自定义事件(可以将类里面的数据传递到组件)
代码(引用的代码在最下面)
import { hintMessage } from '@/utils/hintMessage';
import { toRaw } from 'vue';
// import { useDataOverviewStore } from '@/store';
// import { rectListtype } from '@/store/modules/dataOverview/types';
import Konva from 'konva';
import { Layer } from 'konva/lib/Layer';
import { Stage } from 'konva/lib/Stage';
import { generateString } from './generateString';
import {
convertFourCoodinateToXYWidthHeight,
convertXYWidthHeightToFourCoodinate,
getOffset,
getRectInImageOutside,
getTextCoodinate,
} from './knovaCoordinateCalculation';
import { roundNumber } from './numberHandle';
export default class KnovaDraw {
stage: Stage;
layerShape: Layer;
layerImg: Layer;
// pictureLoading = false;
// 图片缩放倍数
pantographRatio = 1;
config: any;
isDrawRect = false;
// dataOverviewStore: any;
imgOffset = {
x: 0,
y: 0,
};
isTransform = false; // 判断是否正在进行图形变换
_eventHandlers: any
isEditStatus = false
oldAttrs: any = {}
constructor(config: any) {
// this.stage = new Konva.Stage({
// container: document.getElementById('knovaCanvas') as HTMLDivElement,
// width: config.width,
// height: config.height,
// });
// this.dataOverviewStore = useDataOverviewStore();
this.config = config;
this.stage = new Konva.Stage({
container: document.getElementById('knovaCanvas') as HTMLDivElement,
width: config.width,
height: config.height,
draggable: true,
});
this.layerShape = new Konva.Layer();
this.layerImg = new Konva.Layer();
this.init(config.url, this.config.rectList);
this.clickEvent();
this.dblclickEvent();
this.wheelEvent();
this._eventHandlers = {};
}
init(url: string, rectList: any) {
// console.log(url);
// this.drawImg()
const img = new Image();
img.src = url;
// this.pictureLoading = true;
// 清除上一张图片
this.layerImg.removeChildren();
img.onload = () => {
// 获取缩放倍数
this.pantographRatio =
img.width / this.config.width > img.height / this.config.height
? img.width / this.config.width
: img.height / this.config.height;
// if (this.config.isMap) {
// this.drawImg(img, this.config.width * 10, this.config.height * 10);
// } else {
// }
const imgWidth = roundNumber(img.width / this.pantographRatio);
const imgHeight = roundNumber(img.height / this.pantographRatio);
this.imgOffset = getOffset(
imgWidth,
imgHeight,
this.config.width,
this.config.height
);
this.drawImg(img, imgWidth, imgHeight);
// 渲染矩形框数据
this.renderRects(rectList)
// if (this.config.isShowReviewData) {
// } else {
// this.renderRects(this.config.shapeList)
// }
};
this.drawRect();
}
setIsEditStatus(bool: boolean) {
this.isEditStatus = bool
// 控制矩形框是否可以拖动
this.stage.find('.shape').forEach(item => {
item.setAttrs({
...item.attrs,
draggable: bool,
});
})
}
drawImg(img: any, width: number, height: number) {
const imgs = new Konva.Image({
x: 0,
y: 0,
image: img,
width,
height,
offsetX: this.imgOffset.x,
offsetY: this.imgOffset.y,
});
this.layerImg.add(imgs);
this.stage.add(this.layerImg);
}
// 绘制一组矩形框
renderRects(rectList: Array<any>) {
this.layerShape.removeChildren();
rectList.forEach(item => {
const rectParams = {
...convertFourCoodinateToXYWidthHeight(
item.polygon_point_list,
this.pantographRatio,
this.imgOffset
),
id: item.id + '',
};
this.Rect(rectParams)
const textParams = {
id: 'textid' + item.id,
text: item.object_name,
...getTextCoodinate(
item.polygon_point_list,
this.pantographRatio,
this.imgOffset
),
};
this.Text(textParams)
})
this.stage.add(this.layerShape);
}
Rect(payload: any, draggable = false) {
const rect = new Konva.Rect({
...payload,
stroke: 'red',
name: 'shape',
type: 'rect',
strokeWidth: 1,
draggable,
});
this.layerShape.add(rect);
// 添加矩形拖动事件
rect.on('dragstart', (e) => {
this.isTransform = true;
const { attrs } = e.target;
this.oldAttrs = JSON.parse(JSON.stringify(attrs))
})
rect.on('dragend', (e) => {
this.isTransform = false;
// setTimeout(() => {this.isTransform = false;}, 100)
const { attrs } = e.target;
this.modificationRectInfo(attrs);
});
}
deleteShape(id: string) {
this.stage.find(`#${id}`).forEach(item => item.destroy())
}
Text(payload: any) {
const text = new Konva.Text({
...payload,
fontSize: 18,
fill: 'red',
offsetX: 0,
offsetY: 18,
type: 'text',
});
this.layerShape.add(text);
}
updatedText(info: { id: string; text: string}) {
this.stage.find(`#textid${info.id}`).forEach(item => item.setAttrs({...item, text: info.text}))
}
// 让矩形可以变换
transformerFun() {
// console.log('让矩形可以变换1');
this.stage.find('.shape').forEach((item) => {
// console.log('让矩形可以变换');
console.log(item);
const tr = new Konva.Transformer({
anchorStroke: 'red',
// anchorFill: 'yellow',
anchorSize: 4,
borderStroke: 'red',
borderDash: [],
nodes: [item],
id: `Transformer${item.attrs.id}`,
rotateEnabled: false,
name: 'transformer',
});
this.layerShape.add(tr);
tr.on('transformstart', (e) => {
const { attrs } = e.target;
// console.log('start', toRaw(attrs).y);
this.oldAttrs = JSON.parse(JSON.stringify(attrs))
this.isTransform = true;
});
tr.on('transformend', (e) => {
this.isTransform = false;
const { attrs } = e.target;
// console.log(this.imgOffset);
// console.log(attrs.id, attrs);
// this.stage.find(`#${attrs.id}`).forEach((itema) => {
// // const aaa = e.target.attrs;
// // console.log(itema);
// itema.setAttrs({
// width: itema.width() * itema.attrs.scaleX,
// height: itema.height() * itema.attrs.scaleY,
// scaleX: 1,
// scaleY: 1,
// });
// });
console.log('end', attrs.y, this.imgOffset);
// 获取y轴的值,解决插件bug
// const rectX = getRectX(toRaw(attrs).y, toRaw(attrs).scaleY);
const parload = {
id: attrs.id,
x: attrs.x,
y: toRaw(attrs).y,
width: attrs.width * attrs.scaleX,
height: attrs.height * attrs.scaleY,
};
this.modificationRectInfo(parload);
});
});
this.stage.add(this.layerShape);
}
removeTransformerFun() {
this.stage.find('.transformer').forEach(item => item.destroy())
}
// 修改矩形框的位置及大小
modificationRectInfo(attrs: any) {
const newCoordinate = convertXYWidthHeightToFourCoodinate(
attrs.x,
attrs.y,
attrs.width,
attrs.height,
this.pantographRatio,
this.imgOffset
);
console.log('修改矩形框的位置及大小', getRectInImageOutside(
attrs.x,
attrs.y,
this.layerImg.children![0].attrs,
this.stage.attrs,
attrs.width,
attrs.height
));
if (getRectInImageOutside(
attrs.x,
attrs.y,
this.layerImg.children![0].attrs,
this.stage.attrs,
attrs.width,
attrs.height
)) {
hintMessage('warning', '不允许在图片外面绘制信息');
this.stage.find(`#${this.oldAttrs.id}`).forEach(item => {
item.setAttrs({...this.oldAttrs})
// item.setAttrs({...item, x: this.oldAttrs.x, y: this.oldAttrs.y, width: this.oldAttrs.width, height: this.oldAttrs.height})
})
} else {
this.stage.find(`#textid${attrs.id}`).forEach(item => {
item.setAttrs({
...item,
x: attrs.x,
y: attrs.y,
})
})
this.fireEvent('rectCoordinateChange', {
Coordinate: newCoordinate,
id: attrs.id,
})
}
// 更新矩形框位置
// this.dataOverviewStore.updatedRectInfo(attrs.id, newCoordinate);
}
drawRect() {
let initPosition: { x: number; y: number } | null = null;
let shape = new Konva.Rect();
let shapeId = generateString();
// const dataOverviewStore = useDataOverviewStore();
const stageMouseDown = () => {
if (!this.isEditStatus || !this.isDrawRect || this.isTransform) {
// initPosition = null
return;
}
console.log('stageMouseDown');
this.stage.draggable(false);
if (this.stage) {
const RelativePointerPosition = this.stage.getRelativePointerPosition();
initPosition = {
x: RelativePointerPosition!.x,
y: RelativePointerPosition!.y,
};
if (
getRectInImageOutside(
initPosition!.x,
initPosition!.y,
this.layerImg.children![0].attrs,
this.stage.attrs
)
) {
hintMessage('warning', '不允许在图片外面绘制信息');
return;
}
shape.setAttrs({
...initPosition,
stroke: 'red',
id: shapeId,
name: 'shape',
type: 'rect',
});
this.layerShape.add(shape);
this.stage.add(this.layerShape);
}
};
this.stage.on('mousedown', () => {
this.stage.draggable(false);
// const RelativePointerPosition = this.stage.getRelativePointerPosition();
// initPosition = {
// x: RelativePointerPosition!.x,
// y: RelativePointerPosition!.y,
// };
setTimeout(() => {
stageMouseDown()
}, 100)
});
const stageMouseMove = () => {
if (!this.isEditStatus || !this.isDrawRect) {
return;
}
if (this.isTransform) {
initPosition = null
return
}
// console.log('stageMouseMove', initPosition);
if (!initPosition) return;
let x = initPosition?.x;
let y = initPosition?.y;
if (this.stage) {
const RelativePointerPosition = this.stage.getRelativePointerPosition();
const width = Math.abs(initPosition!.x - RelativePointerPosition!.x);
const height = Math.abs(initPosition!.y - RelativePointerPosition!.y);
if (RelativePointerPosition!.x < x!) {
x = RelativePointerPosition!.x;
}
if (RelativePointerPosition!.y < y!) {
y = RelativePointerPosition!.y;
}
shape!.setAttrs({
width,
x,
y,
height,
});
}
};
this.stage.on('mousemove', stageMouseMove);
this.stage.on('mouseup', () => {
if (!this.isEditStatus || !this.isDrawRect || !shape.attrs.id || this.isTransform) {
return;
}
console.log('mouseup');
this.stage.draggable(true);
if (this.stage) {
const labelWidth = shape.getSize().width;
const labelHeight = shape.getSize().height;
const newShape = {
type: 'rect',
x: shape.getPosition().x,
y: shape.getPosition().y,
id: shapeId,
width: labelWidth,
height: labelHeight,
};
if (
getRectInImageOutside(
shape.getPosition().x,
shape.getPosition().y,
this.layerImg.children![0].attrs,
this.stage.attrs,
labelWidth,
labelHeight
)
) {
hintMessage('warning', '不允许在图片外面绘制信息');
} else if (newShape.width > 4 && newShape.height > 4) {
// this.dataOverviewStore.setPopupFormData({
// delect_id: '',
// category_id: '',
// });
// 打开弹出框
// this.dataOverviewStore.setIsShowPopup(true);
// 存储画框信息
const rectPointInfo = convertXYWidthHeightToFourCoodinate(
shape.getPosition().x,
shape.getPosition().y,
labelWidth,
labelHeight,
this.pantographRatio,
this.imgOffset
);
console.log('mouse up');
this.fireEvent('addRect', {
rectPointInfo,
rectInfo: {
x: shape.getPosition().x,
y: shape.getPosition().y,
width: labelWidth,
height: labelHeight,
}
})
// this.dataOverviewStore.setCurrentBBoxInfo(bbox);
}
// shape.setAttrs(newShape);
this.stage.find(`#${shapeId}`).forEach((item) => {
item.destroy();
});
shape = new Konva.Rect();
initPosition = null;
shapeId = generateString();
}
});
}
setIsDrawRect(bool: boolean) {
this.isDrawRect = bool;
}
// 点击事件
clickEvent(): void {
// const dataOverviewStore = useDataOverviewStore();
this.stage.on('click', (e) => {
const { attrs } = e.target;
if (this.isEditStatus && attrs.type === 'rect') {
this.fireEvent('rectClick', attrs)
}
});
}
// 双击事件
dblclickEvent() {
this.stage.on('dblclick', (e) => {
// if (!this.dataOverviewStore.getEditStatus) {
// return;
// }
const { attrs } = e.target;
if (attrs.type === 'rect') {
const bbox = convertXYWidthHeightToFourCoodinate(
attrs.x,
attrs.y,
attrs.width,
attrs.height,
this.pantographRatio,
this.imgOffset
);
// this.dataOverviewStore.setCurrentBBoxInfo(bbox);
// const itemVal = toRaw(this.dataOverviewStore.rectList).find(
// (item: any) => item.delect_id === Number(attrs.id)
// );
// this.dataOverviewStore.setPopupFormData({
// delect_id: itemVal.delect_id,
// category_id: itemVal.delect_detail.category_id,
// });
// this.dataOverviewStore.setIsShowPopup(true);
// dataOverviewStore.setCurrentSelectTable(Number(attrs.id));
}
});
}
// 图片放大缩小
wheelEvent() {
this.stage.on('wheel', (e) => {
const max = 4; // 放大最大的比例
const min = 0.5; // 缩小最小的比例
const step = 0.03; // 每次缩放的比例
const x = e.evt.offsetX;
const y = e.evt.offsetY;
if (this.stage) {
const offsetX =
((x - this.stage.offsetX()) * this.stage.scaleX()) /
(this.stage.scaleX() - step) -
(x - this.stage.offsetX());
const offsetY =
((y - this.stage.offsetY()) * this.stage.scaleY()) /
(this.stage.scaleY() - step) -
(y - this.stage.offsetY());
// eslint-disable-next-line prefer-destructuring
const evt: any = e.evt;
if (evt.wheelDelta) {
if (evt.wheelDelta > 0) {
// 放大
if (this.stage?.scaleX() < max && this.stage?.scaleY() < max) {
// eslint-disable-next-line no-unsafe-optional-chaining
this.stage?.scaleX(this.stage?.scaleX() + step);
// eslint-disable-next-line no-unsafe-optional-chaining
this.stage?.scaleY(this.stage?.scaleY() + step);
this.stage?.move({ x: -offsetX, y: -offsetY }); // 跟随鼠标偏移位置
}
} else {
// 缩小
// eslint-disable-next-line no-lonely-if
if (this.stage?.scaleX() > min && this.stage?.scaleY() > min) {
// eslint-disable-next-line no-unsafe-optional-chaining
this.stage?.scaleX(this.stage?.scaleX() - step);
// eslint-disable-next-line no-unsafe-optional-chaining
this.stage?.scaleY(this.stage?.scaleY() - step);
this.stage?.move({ x: offsetX, y: offsetY }); // 跟随鼠标偏移位置
}
}
}
}
});
}
rectHighlight(id: string) {
// const rectId = id;
// this.stage.find('.shape').forEach((item) => {
// if (item.attrs.id === rectId) {
// item.setAttrs({
// ...item.attrs,
// stroke: 'blue',
// });
// } else {
// item.setAttrs({
// ...item.attrs,
// stroke: 'red',
// });
// }
// });
const rectId = `Transformer${id}`;
this.stage.find('.transformer').forEach((item) => {
console.log(item.attrs.id, rectId);
if (item.attrs.id === rectId) {
item.setAttrs({
...item.attrs,
anchorStroke: 'blue',
borderStroke: 'blue',
});
} else {
item.setAttrs({
...item.attrs,
anchorStroke: 'red',
borderStroke: 'red',
});
}
});
}
// 退出编辑状态
// exitEditStatus() {
// }
// 自定义事件
addEventListener(eventType: string, handler: Function) {
if (!this._eventHandlers[eventType]) {
this._eventHandlers[eventType] = [];
}
this._eventHandlers[eventType].push(handler);
}
removeEventListener(eventType: string, handler: Function) {
if (this._eventHandlers[eventType]) {
const index = this._eventHandlers[eventType].indexOf(handler);
if (index > -1) {
this._eventHandlers[eventType].splice(index, 1);
}
}
}
fireEvent(eventType: string, data: any) {
const handlers = this._eventHandlers[eventType];
if (handlers) {
handlers.forEach((handler: Function) => {
handler(data);
});
}
}
}
// file '@/utils/hintMessage';
import { Message } from '@arco-design/web-vue';
type MessageType = 'info' | 'success' | 'warning' | 'error' | 'loading';
let messageClose: any = null;
export const hintMessage = (type: MessageType, content: string) => {
if (messageClose) {
messageClose.close();
}
messageClose = Message[type]({
content,
closable: true,
});
};
// file './knovaCoordinateCalculation'
import { roundNumber } from "./numberHandle";
/**
* Convert the four coodinate points to x,y,width,height
* @param list two-dimensional array
* @param common_scale Message type
* @returns {x, y, width, height}
*/
export const convertFourCoodinateToXYWidthHeight = (
list: Array<Array<number>>,
common_scale: number,
offset: {
x: number;
y: number;
}
) => {
return {
width: (list[3][0] - list[0][0]) / common_scale,
height: (list[2][1] - list[0][1]) / common_scale,
x: list[0][0] / common_scale - offset.x,
y: list[0][1] / common_scale - offset.y,
};
};
/**
* Getting text coordinates
* @param list two-dimensional array
* @param common_scale Message type
* @returns {x, y}
*/
export const getTextCoodinate = (
list: Array<Array<number>>,
common_scale: number,
offset: {
x: number;
y: number;
}
) => {
return {
x: list[0][0] / common_scale - offset.x,
y: list[0][1] / common_scale - offset.y,
};
};
// Formatting coordinate points
export const formatCoordinatePoints = (
payload: Array<Array<number>>,
common_scale: number
) => {
// const zoom = actualDisplayGraphics.value.zoomValue
if (common_scale) {
const originPoints = payload.map((item) => {
return [item[0] * common_scale, item[1] * common_scale];
});
return originPoints;
}
};
/**
* Convert the x,y,width,height to four coodinate points
* @param x
* @param y
* @param width
* @param height
* @param common_scale Multiple of scale
* @returns Array<Array<Number>>
*/
export const convertXYWidthHeightToFourCoodinate = (
x: number,
y: number,
width: number,
height: number,
common_scale: number,
offset: {
x: number;
y: number;
}
) => {
const arr: Array<Array<number>> = [];
const originX = x + offset.x;
const originY = y + offset.y;
for (let index = 0; index < 4; index++) {
if (index === 0) {
arr.push([roundNumber(originX * common_scale), roundNumber(originY * common_scale)]);
} else if (index === 1) {
arr.push([roundNumber(originX * common_scale), roundNumber((originY + height) * common_scale)]);
} else if (index === 2) {
arr.push([roundNumber((originX + width) * common_scale), roundNumber((originY + height) * common_scale)]);
} else if (index === 3) {
arr.push([roundNumber((originX + width) * common_scale), roundNumber(originY * common_scale)]);
}
}
return arr;
};
export const getOffset = (
imgWidth: number,
imgHeight: number,
knovaWidth: number,
knovaHeight: number
) => {
// console.log(imgWidth, imgHeight, knovaWidth, knovaHeight);
if (imgWidth === knovaWidth) {
return {
x: 0,
y: -((knovaHeight - imgHeight) / 2),
};
}
if (imgHeight === knovaHeight) {
return {
x: -((knovaWidth - imgWidth) / 2),
y: 0,
};
}
return {
x: -((knovaWidth - imgWidth) / 2),
y: -((knovaHeight - imgHeight) / 2),
};
};
/**
* 判断绘制的矩形是否在图片外面
*
*
* @example
*
*
* @type {Function}
*/
export const getRectInImageOutside = (
x: number,
y: number,
imgAttrs: any,
stageAttrs: any,
labelWidth = 0,
labelHeight = 0
) => {
const limitX = {
max: 0,
min: 0,
};
const limitY = {
max: 0,
min: 0,
};
limitX.min = (stageAttrs.width - imgAttrs.width) / 2;
limitY.min = (stageAttrs.height - imgAttrs.height) / 2;
limitX.max = imgAttrs.width + limitX.min;
limitY.max = imgAttrs.height + limitY.min;
let bool = false;
if (labelWidth) {
if (
x + labelWidth < limitX.min ||
x + labelWidth > limitX.max ||
y + labelHeight < limitY.min ||
y + labelHeight > limitY.max
) {
bool = true;
}
}
if (
x < limitX.min ||
x > limitX.max ||
y < limitY.min ||
y > limitY.max ||
bool
) {
return true;
}
return false;
};
// file './numberHandle'
// 数字取整
// eslint-disable-next-line import/prefer-default-export
export function roundNumber(num: number): number {
return Math.round(num);
}
多边形
drawPolygon() {
console.log(111, this.stage);
const initLine = {
id: generateId() + '',
type: "polygon",
stroke: "black",
strokeWidth: 5,
fill: "red",
};
let polygonShape = new Konva.Line(initLine)
// 这个是辅助线
let auxiliaryLine = new Konva.Line({
points: [],
stroke: "green",
strokeWidth: 2,
lineJoin: "round",
dash: [10],
});
let path = []
const onMousedown = ({evt}) => {
// if ()
if (!polygonShape) { return }
console.log(222);
const x = evt.offsetX;
const y = evt.offsetY;
// 判断有没有闭合,方便操作,当点击到起始位置的一定范围内即视为闭合
if (Math.abs(path?.[0] - x) <= 5 && Math.abs(path?.[1] - y) <= 5) {
console.log(333);
auxiliaryLine.destroy();
polygonShape.destroy();
polygonShape = new Konva.Line(initLine)
auxiliaryLine = new Konva.Line({
points: [],
stroke: "green",
strokeWidth: 2,
lineJoin: "round",
dash: [10],
});
this.polygon(path, generateId() + '', 'blue', this.fixedShapeName)
path = []
return;
}
console.log(444);
path.push(...[x, y]);
polygonShape.setAttrs({ points: path });
// path只有2个位置(一对x,y)就代表第一次插入,把图形放到 layer 里
if (path.length === 2) {
this.fixedLayer.add(auxiliaryLine);
this.fixedLayer.add(polygonShape);
}
this.stage.add(this.fixedLayer)
}
const onMouseMove = ({evt}) => {
const closePathX = path[0];
const closePathY = path[1];
const lastPathX = path[path.length - 2];
const lastPathY = path[path.length - 1];
const x = evt.offsetX;
const y = evt.offsetY;
if (!lastPathX || !lastPathY) return;
//做个吸附效果,如果鼠标当前位置非常接近闭合点,把线移动过去
if (Math.abs(closePathX - x) <= 5 && Math.abs(closePathY - y) <= 5) {
auxiliaryLine.setAttrs({
points: [lastPathX, lastPathY, closePathX, closePathY],
});
} else {
// 辅助线的第一个点永远是 path 的最后一个位置,第二个点是当前鼠标所在的点
auxiliaryLine.setAttrs({
points: [lastPathX, lastPathY, x, y],
});
}
}
this.stage.on('mousedown', onMousedown)
this.stage.on("mousemove", onMouseMove);
}
线段
drawLine() {
console.log(111, this.stage);
const initLine = {
id: generateId() + '',
type: "polygon",
stroke: "black",
strokeWidth: 5,
fill: "red",
};
let polygonShape = new Konva.Line(initLine)
// 这个是辅助线
let auxiliaryLine = new Konva.Line({
points: [],
stroke: "green",
strokeWidth: 2,
lineJoin: "round",
dash: [10],
});
let path = []
const onMousedown = ({evt}) => {
// if ()
if (!polygonShape) { return }
console.log(222);
const x = evt.offsetX;
const y = evt.offsetY;
path.push(...[x, y]);
// 判断有没有闭合,方便操作,当点击到起始位置的一定范围内即视为闭合
if (path.length === 4) {
console.log(333);
auxiliaryLine.destroy();
polygonShape.destroy();
polygonShape = new Konva.Line(initLine)
auxiliaryLine = new Konva.Line({
points: [],
stroke: "green",
strokeWidth: 2,
lineJoin: "round",
dash: [10],
});
// console.log();
// path.push(...[x, y]);
this.polygon(path, generateId() + '', 'blue', this.fixedShapeName)
path = []
return;
}
console.log(444);
polygonShape.setAttrs({ points: path });
// path只有2个位置(一对x,y)就代表第一次插入,把图形放到 layer 里
if (path.length === 2) {
this.fixedLayer.add(auxiliaryLine);
this.fixedLayer.add(polygonShape);
}
this.stage.add(this.fixedLayer)
}
const onMouseMove = ({evt}) => {
const lastPathX = path[path.length - 2];
const lastPathY = path[path.length - 1];
const x = evt.offsetX;
const y = evt.offsetY;
if (!lastPathX || !lastPathY) return;
auxiliaryLine.setAttrs({
points: [lastPathX, lastPathY, x, y],
});
}
this.stage.on('mousedown', onMousedown)
this.stage.on("mousemove", onMouseMove);
}