<template> <div> <el-button @click="show">展示</el-button> <el-button @click="create">创建</el-button> <el-button @click="edit">编辑</el-button> <canvas id="editPolygon" width="800" height="400" tabindex="0" /> </div> </template> <script lang='ts'> import { SGraphItem, SGraphView, SGraphScene } from "@saga-web/graph/"; import { SMouseEvent } from "@saga-web/base/"; import { SColor, SLineCapStyle, SPainter, SPath2D, SPoint, SPolygonUtil, SRect, SLine } from "@saga-web/draw"; import { SRelationState } from "@saga-web/big/lib/enums/SRelationState"; import { SMathUtil } from "@saga-web/big/lib/utils/SMathUtil"; export default { data() { return { scene: null, view: null }; }, mounted(): void { this.view = new SGraphView("editPolygon"); }, methods: { show() { const scene = new SGraphScene(); this.view.scene = scene; const spolygonItem = new SPolygonItem(null); spolygonItem.setStatus = SRelationState.Normal; const PointList: SPoint[] = [ new SPoint(0, 0), new SPoint(50, 0), new SPoint(50, 50), new SPoint(0, 50) ]; spolygonItem.setPointList = PointList; scene.addItem(spolygonItem); this.view.fitSceneToView(); }, create() { const scene = new SGraphScene(); this.view.scene = scene; const spolygonItem = new SPolygonItem(null); spolygonItem.setStatus = SRelationState.Create; scene.addItem(spolygonItem); scene.grabItem = spolygonItem; this.view.fitSceneToView(); }, edit() { const scene = new SGraphScene(); this.view.scene = scene; const spolygonItem = new SPolygonItem(null); spolygonItem.setStatus = SRelationState.Edit; const PointList: SPoint[] = [ new SPoint(0, 0), new SPoint(50, 0), new SPoint(50, 60), new SPoint(0, 50) ]; spolygonItem.setPointList = PointList; scene.addItem(spolygonItem); scene.grabItem = spolygonItem; this.view.fitSceneToView(); } } }; /** * @author hanyaolong */ class SPolygonItem extends SGraphItem { /** X坐标最小值 */ private minX = Number.MAX_SAFE_INTEGER; /** X坐标最大值 */ private maxX = Number.MIN_SAFE_INTEGER; /** Y坐标最小值 */ private minY = Number.MAX_SAFE_INTEGER; /** Y坐标最大值 */ private maxY = Number.MIN_SAFE_INTEGER; /** 轮廓线坐标 */ private pointList: SPoint[] = []; // 获取当前状态 get getPointList(): SPoint[] { return this.pointList; } // 编辑当前状态 set setPointList(arr: SPoint[]) { this.pointList = arr; if (arr) { this._xyzListToSPointList(arr); } this.update(); } /** 是否闭合 */ closeFlag: boolean = false; // 当前状态 1:show 2 创建中,3 编辑中 _status: number = SRelationState.Normal; // 获取当前状态 get getStatus(): number { return this._status; } // 编辑当前状态 set setStatus(value: number) { this._status = value; this.update(); } /** 边框颜色 */ borderColor: SColor = new SColor("#0091FF"); /** 填充颜色 */ brushColor: SColor = new SColor("#1EE887"); /** border宽 只可输入像素宽*/ borderLine: number = 4; /** 鼠标移动点 */ private lastPoint = new SPoint(); /** 当前鼠标获取顶点对应索引 */ private curIndex: number = -1; /** 灵敏像素 */ private len: number = 15; /** 场景像素 */ private scenceLen: number = 15; /** 场景像素 */ private isAlt: boolean = false; /** * 构造函数 * * @param parent 指向父对象 */ constructor(parent: SGraphItem | null) { super(parent); } ///////////////以下为对pointList 数组的操作方法 /** * 储存新的多边形顶点 * @param x 点位得x坐标 * @param y 点位得y坐标 * @param i 储存所在索引 * @return SPoint */ insertPoint(x: number, y: number, i: number | null = null): SPoint { const point = new SPoint(x, y); if (i == null) { this.pointList.push(point); } else { this.pointList.splice(i, 0, point); } this.update(); return point; } /** * 删除点位 * @param i 删除点所在的索引 * @return SPoint */ deletePoint(i: number | null = null): SPoint | null | undefined { let point = null; if (i != null) { if (this.pointList.length - 1 >= i) { point = this.pointList[i]; this.pointList.splice(i, 1); } else { point = null; } } else { point = this.pointList.pop(); } this.update(); return point; } /** * 多边形顶点的移动位置 * @param x 点位得x坐标 * @param y 点位得y坐标 * @param i 点位得i坐标 * @return SPoint */ movePoint(x: number, y: number, i: number): SPoint | null | undefined { let point = null; if (this.pointList.length) { this.pointList[i].x = x; this.pointList[i].y = y; } point = this.pointList[i]; return point; } /** * 打印出多边形数组 * @return SPoint[] */ PrintPointList(): SPoint[] { return this.pointList; } /////////////////////////// /** * xyz数据转换为SPoint格式函数;获取外接矩阵参数 * * @param arr 外层传入的数据PointList */ protected _xyzListToSPointList(arr: SPoint[]): void { if (arr.length) { this.pointList = arr.map(it => { let x = it.x, y = it.y; if (x < this.minX) { this.minX = x; } if (y < this.minY) { this.minY = y; } if (x > this.maxX) { this.maxX = x; } if (y > this.maxY) { this.maxY = y; } return new SPoint(x, y); }); } else { this.pointList = []; } } ////////////以下为三种状态下的绘制多边形方法 /** * 展示状态 --绘制多边形数组 * @param painter 绘制类 * @param pointList 绘制多边形数组 * */ protected drawShowPolygon(painter: SPainter, pointList: SPoint[]): void { painter.pen.lineCapStyle = SLineCapStyle.Square; painter.pen.color = this.borderColor; painter.pen.lineWidth = painter.toPx(this.borderLine); painter.brush.color = this.brushColor; painter.drawPolygon([...pointList]); } /** * * 创建状态 --绘制多边形数组 * @param painter 绘制类 * @param pointList 绘制多边形数组 * */ protected drawCreatePolygon(painter: SPainter, pointList: SPoint[]): void { painter.pen.lineCapStyle = SLineCapStyle.Square; painter.pen.color = this.borderColor; painter.pen.lineWidth = painter.toPx(4); painter.drawPolyline(pointList); if (this.lastPoint) { painter.drawLine(pointList[pointList.length - 1], this.lastPoint); } painter.pen.color = SColor.Transparent; painter.brush.color = this.brushColor; painter.pen.lineWidth = painter.toPx(4); painter.drawPolygon([...pointList, this.lastPoint]); } /** * * 编辑状态 --绘制多边形数组 * * @param painter 绘制类 * @param pointList 绘制多边形数组 * * */ protected drawEditPolygon(painter: SPainter, pointList: SPoint[]): void { // 展示多边形 this.drawShowPolygon(painter, pointList); // 绘制顶点块 pointList.forEach((item, index) => { painter.drawCircle(item.x, item.y, painter.toPx(8)); }); } //////////////////////////////// /** * 编辑状态操作多边形数组 * * @param event 鼠标事件 * * * */ protected editPolygonPoint(event: SMouseEvent): void { // 判断是否为删除状态 isAlt = true为删除状态 if (this.isAlt) { // 1 判断是否点击在多边形顶点 let lenIndex = -1; // 当前点击到的点位索引; let curenLen = this.scenceLen; // 当前的灵敏度 this.pointList.forEach((item, index) => { let dis = SMathUtil.pointDistance(event.x, event.y, item.x, item.y); if (dis < curenLen) { curenLen = dis; lenIndex = index; } }); // 若点击到,对该索引对应的点做删除 if (lenIndex != -1) { if (this.pointList.length <= 3) { return; } this.deletePoint(lenIndex); } } else { // 1 判断是否点击在多边形顶点 this.curIndex = -1; let lenIndex = -1; // 当前点击到的点位索引; let curenLen = this.scenceLen; // 当前的灵敏度 this.pointList.forEach((item, index) => { let dis = SMathUtil.pointDistance(event.x, event.y, item.x, item.y); if (dis < curenLen) { curenLen = dis; lenIndex = index; } }); this.curIndex = lenIndex; // 2判断是否点击在多边形得边上 if (-1 == lenIndex) { let len = SMathUtil.pointToLine( new SPoint(event.x, event.y), new SLine(this.pointList[0], this.pointList[1]) ), index = 0; if (this.pointList.length > 2) { for (let i = 1; i < this.pointList.length; i++) { let dis = SMathUtil.pointToLine( new SPoint(event.x, event.y), new SLine(this.pointList[i], this.pointList[i + 1]) ); if (i + 1 == this.pointList.length) { dis = SMathUtil.pointToLine( new SPoint(event.x, event.y), new SLine(this.pointList[i], this.pointList[0]) ); } if (dis.MinDis < len.MinDis) { len = dis; index = i; } } } // 如果再线上则为新增点 if (len.Point) { if (len.MinDis <= this.scenceLen) { this.pointList.splice(index + 1, 0, len.Point); } } } // 刷新视图 this.update(); } } ///////////////////////////////以下为鼠标事件 /** * 鼠标双击事件 * * @param event 事件参数 * @return boolean */ onDoubleClick(event: SMouseEvent): boolean { // 如果位show状态 双击改对象则需改为编辑状态 if (SRelationState.Normal == this._status) { this._status = SRelationState.Edit; } else if (SRelationState.Edit == this._status) { this._status = SRelationState.Normal; } this.update(); return true; } // Function onDoubleClick() /** * 键盘事件 * * @param event 事件参数 * @return boolean */ onKeyDown(event: KeyboardEvent): boolean { console.log(event); if (this._status == SRelationState.Normal) { return false; } else if (this._status == SRelationState.Create) { if (event.code == "Enter") { this._status = SRelationState.Normal; } } else if (this._status == SRelationState.Edit) { if (event.key == "Alt") { this.isAlt = true; } } else { } this.update(); return true; } // Function onKeyDown() /** * 键盘键抬起事件 * * @param event 事件参数 * @return boolean */ onKeyUp(event: KeyboardEvent): boolean { if (this._status == SRelationState.Edit) { if (event.key == "Alt") { this.isAlt = false; } } this.update(); return true; } // Function onKeyUp() /** * 鼠标按下事件 * * @param event 事件参数 * @return boolean */ onMouseDown(event: SMouseEvent): boolean { console.log("aaaaaa"); // 如果状态为编辑状态则添加点 if (this._status == SRelationState.Create) { // 新增顶点 this.insertPoint(event.x, event.y); } else if (this._status == SRelationState.Edit) { // 对多边形数组做编辑操作 this.editPolygonPoint(event); } return true; } // Function onMouseDown() /** * 鼠标移入事件 * * @param event 事件参数 * @return boolean */ onMouseEnter(event: SMouseEvent): boolean { return true; } // Function onMouseEnter() /** * 鼠标移出事件 * * @param event 事件参数 * @return boolean */ onMouseLeave(event: SMouseEvent): boolean { return true; } // Function onMouseLeave() /** * 鼠标移动事件 * * @param event 事件参数 * @return boolean */ onMouseMove(event: SMouseEvent): boolean { if (this._status == SRelationState.Create) { this.lastPoint.x = event.x; this.lastPoint.y = event.y; } else if (this._status == SRelationState.Edit) { if (-1 != this.curIndex) { this.pointList[this.curIndex].x = event.x; this.pointList[this.curIndex].y = event.y; } } this.update(); return true; } // Function onMouseMove() /** * 鼠标抬起事件 * * @param event 事件参数 * @return boolean */ onMouseUp(event: SMouseEvent): boolean { if (this._status == SRelationState.Edit) { this.curIndex = -1; } return true; } // Function onMouseUp() /** * 适配事件 * * @param event 事件参数 * @return boolean */ onResize(event: SMouseEvent): boolean { return true; } // Function onResize() /** * Item对象边界区域 * * @return SRect */ boundingRect(): SRect { return new SRect( this.minX, this.minY, this.maxX - this.minX, this.maxY - this.minY ); } // Function boundingRect() /** * Item绘制操作 * * @param painter painter对象 */ onDraw(painter: SPainter): void { this.scenceLen = painter.toPx(this.len); // 当状态为展示状态 if (this._status == SRelationState.Normal) { // 闭合多边形 this.drawShowPolygon(painter, this.pointList); } else if (this._status == SRelationState.Create) { // 创建状态 this.drawCreatePolygon(painter, this.pointList); } else { // 编辑状态 this.drawEditPolygon(painter, this.pointList); } } // Function onDraw() } </script>