import { SColor, SLine, SPainter, SPoint } from "@saga-web/draw/lib"; import { SMouseEvent } from "@saga-web/base"; import { SItemStatus } from ".."; import { SMathUtil } from "../utils/SMathUtil"; import { SGraphItem } from "@saga-web/graph/lib"; /** * 直线item * * */ export class SPolylineItem extends SGraphItem { /** 折点信息 */ pointList: SPoint[] = []; /** 是否绘制完成 */ _status: SItemStatus = SItemStatus.Create; get status(): SItemStatus { return this._status; } set status(v: SItemStatus) { this._status = v; this.update(); } /** 鼠标移动时的点 */ lastPoint: SPoint | null = null; /** 线条颜色 */ _strokeColor: string = "#000000"; get strokeColor(): string { return this._strokeColor; } set strokeColor(v: string) { this._strokeColor = v; this.update(); } /** 填充色 */ _fillColor: string = "#2196f3"; get fillColor(): string { return this._fillColor; } set fillColor(v: string) { this._fillColor = v; this.update(); } /** 线条宽度 */ _lineWidth: number = 1; get lineWidth(): number { return this._lineWidth; } set lineWidth(v: number) { this._lineWidth = v; this.update(); } /** 全局灵敏度 */ dis: number = 10; /** 灵敏度转换为场景长度 */ sceneDis: number = 10; /** 当前点索引 */ curIndex: number = -1; /** * 构造函数 * * @param parent 父级 * @param list 坐标集合 * */ constructor(parent: null | SGraphItem, list: SPoint[]); /** * 构造函数 * * @param parent 父级 * @param list 第一个坐标 * */ constructor(parent: null | SGraphItem, list: SPoint); /** * 构造函数 * * @param parent 父级 * @param list 第一个坐标|坐标集合 * */ constructor(parent: null | SGraphItem, list: SPoint | SPoint[]) { super(parent); if (list instanceof SPoint) { this.pointList.push(list); } else { this.pointList = list; } } // Constructor /** * 添加点至数组中 * * @param p 添加的点 * @param index 添加到的索引 * */ private addPoint(p: SPoint, index?: number): void { if (index && this.canHandle(index)) { this.pointList.splice(index, 0, p); } else { this.pointList.push(p); } this.update(); } // Function addPoint() /** * 是否可以添加点到数组中 * * @param index 要添加到的索引 * @return boolean 是否可添加 * */ private canHandle(index: number): boolean { return index >= 0 && index <= this.pointList.length; } // Function canHandle() /** * 添加点至数组中 * * @param index 添加到的索引 * */ private delPoint(index: number): void { if (this.canHandle(index) && this.pointList.length > 2) { this.pointList.splice(index, 0); this.update(); } } // Function delPoint /** * 鼠标按下事件 * * @param event 鼠标事件 * @return boolean 是否处理事件 * */ onMouseDown(event: SMouseEvent): boolean { this.curIndex = -1; if (event.buttons == 1) { if (this.status == SItemStatus.Create) { this.addPoint(new SPoint(event.x, event.y)); return true; } else if (this.status == SItemStatus.Edit) { // 查询鼠标最近的索引 this.findNearestPoint(new SPoint(event.x, event.y)); // 增加点 // 删除点 if (event.altKey && this.canHandle(this.curIndex)) { this.pointList.splice(this.curIndex, 1); this.curIndex = -1; } this.update(); return true; } else { return super.onMouseDown(event); } } return super.onMouseDown(event); } // Function onMouseDown() /** * 鼠标移动事件 * * @param event 鼠标事件 * @return boolean 是否处理事件 * */ onMouseMove(event: SMouseEvent): boolean { if (this.status == SItemStatus.Create) { if (this.lastPoint) { this.lastPoint.x = event.x; this.lastPoint.y = event.y; } else { this.lastPoint = new SPoint(event.x, event.y); } this.update(); return true; } else if (this.status == SItemStatus.Edit) { if (this.canHandle(this.curIndex)) { this.pointList[this.curIndex].x = event.x; this.pointList[this.curIndex].y = event.y; } this.update(); return true; } else { return super.onMouseMove(event); } } // Function onMouseMove() /** * 鼠标移动事件 * * @param event 鼠标事件 * @return boolean 是否处理事件 * */ onMouseUp(event: SMouseEvent): boolean { this.curIndex = -1; return true; } // Function onMouseMove() /** * 鼠标双击事件 * * @param event 事件参数 * @return boolean */ onDoubleClick(event: SMouseEvent): boolean { if (this.status == SItemStatus.Normal) { this.status = SItemStatus.Edit; } else if (this.status == SItemStatus.Edit) { this.status = SItemStatus.Normal; } else if (this.status == SItemStatus.Create) { this.status = SItemStatus.Edit; } this.$emit("onDoubleClick", event); return true; } // Function onDoubleClick() /*** * 键盘按键弹起事件 * * @param event 事件参数 */ onKeyUp(event: KeyboardEvent): void { if (event.keyCode == 13) { this.status = SItemStatus.Edit; } } // Function onKeyUp() /** * 获取点击点与点集中距离最近点 * * @param p 鼠标点击点 * */ findNearestPoint(p: SPoint): void { let len = this.sceneDis; for (let i = 0; i < this.pointList.length; i++) { let dis = SMathUtil.pointDistance( p.x, p.y, this.pointList[i].x, this.pointList[i].y ); if (dis < len) { len = dis; this.curIndex = i; } } } // Function findNearestPoint() /** * 计算增加点的位置 * * @param p 鼠标点击点 * */ findAddPos(p: SPoint): void { let len = { MinDis: this.sceneDis }, index = 0; if (this.pointList.length > 2) { for (let i = 0; i < this.pointList.length - 1; i++) { let dis = SMathUtil.pointToLine( new SPoint(p.x, p.y), new SLine(this.pointList[i], this.pointList[i + 1]) ); if (dis.MinDis < len.MinDis) { len = dis; index = i; } } // @ts-ignore if (len.Point) { // @ts-ignore this.addPoint(new SPoint(len.Point.X, len.Point.Y), index); } } } // Function findAddPos() /** * 判断点是否在区域内 * * @param x * @param y * @return true-是 */ contains(x: number, y: number): boolean { let p = new SPoint(x, y); for (let i = 1; i < this.pointList.length; i++) { let PTL = SMathUtil.pointToLine( p, new SLine( this.pointList[i - 1].x, this.pointList[i - 1].y, this.pointList[i].x, this.pointList[i].y ) ); if (PTL.MinDis < this.sceneDis) { return true; } } return false; } // Function contains() /** * Item绘制操作 * * @param painter painter对象 */ onDraw(painter: SPainter): void { // 缓存场景长度 this.sceneDis = painter.toPx(this.dis); // 绘制基本图形 painter.pen.lineWidth = painter.toPx(this.lineWidth); painter.pen.color = new SColor(this.strokeColor); painter.drawPolyline(this.pointList); // 创建状态 if (this.status == SItemStatus.Create && this.lastPoint) { painter.drawLine( this.pointList[this.pointList.length - 1], this.lastPoint ); } else if (this.status == SItemStatus.Edit) { // 编辑状态 this.pointList.forEach((t, i): void => { painter.brush.color = SColor.White; if (i == this.curIndex) { painter.brush.color = new SColor(this.fillColor); } painter.drawCircle(t.x, t.y, painter.toPx(5)); }); } } // Function onDraw() } // Class SPolylineItem