123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680 |
- /*
- * ********************************************************************************************************************
- *
- * :*$@@%$*: ;: ;; ;;
- * :@@%! :!@@%: %! ;%%@@%$ =@@@@@@@%; @%@@@%%%%@@@@@
- * :@%; :$= %%$$$%$$ ;$$ ;$@= !@$
- * =@! %! @ $=;% !@@@%: !$$$$$$$$$$$$$$=
- * =@* %! @ $= % %@= =%@! %=
- * *$%%! @@= ;=$%%%$*: %! @ $= % =%%%%%%@$ *%: =%
- * %@@!: !@@@%=$@@@@%! :*@@$: %! @ $= % $* ;@ @* :%*
- * ;@@! ;!!!;: ;@%: =======@%========* @ $$ % $%*****$@ :@$=*********=@$
- * $@* ;@@@%=!: *@*
- * =@$ ;;;!=%@@@@=! =@!
- * %@$: =@%: :*@@@* %@= Copyright (c) 2016-2019. 北京上格云技术有限公司
- * ;%@@$=$@@%* *@@@$=%@@%;
- * ::;:: ::;:: All rights reserved.
- *
- * ********************************************************************************************************************
- */
- import { SGraphItem, SGraphPointListInsert, SGraphPointListDelete, SGraphPointListUpdate } from "@saga-web/graph/lib";
- import { SMouseEvent, SUndoStack } from "@saga-web/base/";;
- import {
- SColor,
- SLineCapStyle,
- SPainter,
- SPoint,
- SRect,
- SLine,
- SPolygonUtil
- } from "@saga-web/draw";
- import { SMathUtil } from "@saga-web/big/lib/utils/SMathUtil";
- import { SItemStatus } from "@saga-web/big";
- /**
- * 编辑多边形
- *
- * @author 韩耀龙
- */
- export 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;
- this.update();
- };
- /** 是否闭合 */
- closeFlag: boolean = false;
- // 当前状态
- protected _status: number = SItemStatus.Normal;
- // 获取当前状态
- get status(): SItemStatus {
- return this._status;
- }
- // 编辑当前状态
- set status(value: SItemStatus) {
- this._status = value;
- // 如果状态为show则需清栈
- if (value == SItemStatus.Normal) {
- if (this.undoStack) {
- this.undoStack.clear();
- }
- }
- this.update();
- };
- data: any | null = null;
- /** 边框颜色 */
- _strokeColor: SColor = new SColor("#0091FF");
- /** 画笔颜色 */
- get strokeColor(): SColor {
- return this._strokeColor
- };
- set strokeColor(v: SColor) {
- this._strokeColor = v
- }
- /** 填充颜色 */
- _fillColor: SColor = new SColor("#1EE887");
- get fillColor(): SColor {
- return this._fillColor
- };
- set fillColor(v: SColor) {
- this._fillColor = v
- }
- /** 边框的宽 只可输入像素宽*/
- _lineWidth: number = 4;
- get lineWidth(): number {
- return this._lineWidth
- }
- set lineWidth(v: number) {
- this._lineWidth = v;
- this.update();
- };
- /** 鼠标移动点 */
- private lastPoint: SPoint | null = null;
- /** 当前鼠标获取顶点对应索引 */
- private curIndex: number = -1;
- /** 当前鼠标获取顶点对应坐标 */
- private curPoint: null | SPoint = null
- /** 灵敏像素 */
- private len: number = 10;
- /** 场景像素 内部将灵敏像素换算为场景实际距离 */
- private scenceLen: number = 15;
- /** 场景像素 */
- private isAlt: boolean = false;
- /** undoredo堆栈 */
- protected undoStack: SUndoStack | null = new SUndoStack();
- /**
- * 构造函数
- *
- * @param parent 指向父对象
- * @param data PolygonData数据
- */
- 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|null。索引不在数组范围则返回null
- */
- deletePoint(i: number | null = null): SPoint | null {
- let point = null;
- if (i != null) {
- if (i >= (this.pointList.length) || i < 0) {
- point = null
- } else {
- point = new SPoint(this.pointList[i].x, this.pointList[i].y);
- this.pointList.splice(i, 1);
- }
- } else {
- if (this.pointList.length) {
- point = this.pointList[this.pointList.length - 1];
- this.pointList.pop();
- } else {
- point = null
- }
- }
- this.update()
- return point
- }
- /**
- * 多边形顶点的移动位置
- *
- * @param x 点位得x坐标
- * @param y 点位得y坐标
- * @param i 点位得i坐标
- * @return 移动对应得点。如果索引无法找到移动顶点,则返回null
- */
- movePoint(x: number, y: number, i: number, ): SPoint | null {
- let point = null;
- if (i >= (this.pointList.length) || i < 0) {
- return null
- }
- if (this.pointList.length) {
- this.pointList[i].x = x;
- this.pointList[i].y = y;
- }
- point = this.pointList[i];
- return point
- }
- /**
- * 打印出多边形数组
- *
- * @return 顶点数组
- */
- PrintPointList(): SPoint[] {
- return this.pointList
- }
- ////////////
- // 以下为三种状态下的绘制多边形方法
- /**
- * 展示状态 --绘制多边形数组
- *
- * @param painter 绘制类
- * @param pointList 绘制多边形数组
- */
- protected drawShowPolygon(painter: SPainter, pointList: SPoint[]): void {
- painter.pen.lineCapStyle = SLineCapStyle.Square;
- painter.pen.color = this._strokeColor;
- painter.pen.lineWidth = painter.toPx(this._lineWidth);
- painter.brush.color = this._fillColor;
- painter.drawPolygon([...pointList]);
- }
- /**
- * 创建状态 --绘制多边形数组
- *
- * @param painter 绘制类
- * @param pointList 绘制多边形数组
- */
- protected drawCreatePolygon(painter: SPainter, pointList: SPoint[]): void {
- painter.pen.lineCapStyle = SLineCapStyle.Square;
- painter.pen.color = this._strokeColor;
- painter.pen.lineWidth = painter.toPx(this._lineWidth);
- if (this.lastPoint && pointList.length) {
- painter.drawLine(pointList[pointList.length - 1].x, pointList[pointList.length - 1].y, this.lastPoint.x, this.lastPoint.y);
- }
- painter.drawPolyline(pointList);
- painter.pen.color = SColor.Transparent;
- painter.brush.color = this._fillColor;
- painter.pen.lineWidth = painter.toPx(this._lineWidth);
- if (this.lastPoint) {
- painter.drawPolygon([...pointList, this.lastPoint]);
- } else {
- painter.drawPolygon(pointList);
- }
- }
- /**
- *
- * 编辑状态 --绘制多边形数组
- *
- * @param painter 绘制类
- * @param pointList 绘制多边形数组
- */
- protected drawEditPolygon(painter: SPainter, pointList: SPoint[]): void {
- // 展示多边形
- this.drawShowPolygon(painter, pointList);
- // 绘制顶点块
- painter.pen.color = SColor.Black;
- painter.brush.color = SColor.White;
- pointList.forEach((item, index) => {
- painter.drawCircle(item.x, item.y, painter.toPx(this.len / 2))
- })
- }
- /**
- * 编辑状态操作多边形数组
- *
- * @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
- }
- const delePoint = new SPoint(this.pointList[lenIndex].x, this.pointList[lenIndex].y)
- this.deletePoint(lenIndex);
- // 记录顶点操作记录压入堆栈
- this.recordAction(SGraphPointListDelete, [this.pointList, delePoint, lenIndex]);
- }
- } else {
- // 1 判断是否点击在多边形顶点
- this.curIndex = -1;
- this.curPoint = null;
- 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) {
- console.log(index,len.Point);
- // 点在了多边形的边上
- if (len.MinDis <= this.scenceLen) {
- this.pointList.splice(index + 1, 0, len.Point);
- // 记录新增顶点操作记录压入堆栈
- this.recordAction(SGraphPointListInsert, [this.pointList, len.Point, index + 1]);
- } else { //没点在多边形边上也没点在多边形顶点上
- super.onMouseDown(event);
- }
- }
- } else {
- // 当捕捉到顶点后 ,记录当前点的xy坐标,用于undo、redo操作
- this.curPoint = new SPoint(this.pointList[this.curIndex].x, this.pointList[this.curIndex].y);
- }
- // 刷新视图
- this.update();
- }
- }
- /////////////////////
- // undo、redo相关操作
- /**
- * 记录相关动作并推入栈中
- * @param SGraphCommand 相关命令类
- * @param any 对应传入参数
- */
- protected recordAction(SGraphCommand: any, any: any[]): void {
- // 记录相关命令并推入堆栈中
- const sgraphcommand = new SGraphCommand(this, ...any);
- if (this.undoStack) {
- this.undoStack.push(sgraphcommand);
- }
- }
- /**
- * 执行取消操作执行
- */
- undo(): void {
- if (this.status == SItemStatus.Normal) {
- return
- }
- if (this.undoStack) {
- this.undoStack.undo();
- }
- }
- /**
- * 执行重做操作执行
- */
- redo(): void {
- if (this.status == SItemStatus.Normal) {
- return
- }
- if (this.undoStack) {
- this.undoStack.redo();
- }
- }
- ///////////////////////////////
- // 以下为鼠标事件
- /**
- * 鼠标双击事件
- *
- * @param event 事件参数
- * @return boolean
- */
- onDoubleClick(event: SMouseEvent): boolean {
- // 如果位show状态 双击改对象则需改为编辑状态
- if (SItemStatus.Normal == this.status) {
- this.status = SItemStatus.Edit;
- this.grabItem(this);
- } else if (SItemStatus.Edit == this.status) {
- this.status = SItemStatus.Normal;
- this.releaseItem();
- if (this.undoStack) {
- this.undoStack.clear()
- }
- }
- this.update()
- return true;
- } // Function onDoubleClick()
- /**
- * 键盘事件
- *
- * @param event 事件参数
- * @return boolean
- */
- onKeyDown(event: KeyboardEvent): boolean {
- if (this.status == SItemStatus.Normal) {
- return false;
- } else if (this.status == SItemStatus.Create) {
- if (event.code == 'Enter') {
- // 当顶点大于二个时才又条件执行闭合操作并清空堆栈
- if (this.pointList.length > 2) {
- this.status = SItemStatus.Normal;
- //3 传递完成事件状态
- this.$emit('finishCreated')
- //1 grabItem 置为null
- this.releaseItem();
- //2 清空undo
- if (this.undoStack) {
- this.undoStack.clear();
- }
- }
- }
- } else if (this.status == SItemStatus.Edit) {
- if (event.key == 'Alt') {
- this.isAlt = true;
- }
- }
- this.update();
- return true;
- } // Function onKeyDown()
- /**
- * 键盘键抬起事件
- *
- * @param event 事件参数
- * @return boolean
- */
- onKeyUp(event: KeyboardEvent): void {
- if (this.status == SItemStatus.Edit) {
- if (event.key == 'Alt') {
- this.isAlt = false;
- }
- }
- this.update()
- } // Function onKeyUp()
- /**
- * 鼠标按下事件
- *
- * @param event 事件参数
- * @return boolean
- */
- onMouseDown(event: SMouseEvent): boolean {
- // 如果状态为编辑状态则添加点
- if (this.status == SItemStatus.Create) {
- // 新增顶点
- this.insertPoint(event.x, event.y);
- // 记录新增顶点操作记录压入堆栈
- let pos = new SPoint(event.x, event.y);
- this.recordAction(SGraphPointListInsert, [this.pointList, pos]);
- } else if (this.status == SItemStatus.Edit) {
- // 对多边形数组做编辑操作
- this.editPolygonPoint(event);
- } else {
- return super.onMouseDown(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 == SItemStatus.Create) {
- this.lastPoint = new SPoint
- this.lastPoint.x = event.x;
- this.lastPoint.y = event.y;
- this.update();
- } else if (this.status == SItemStatus.Edit) {
- if (-1 != this.curIndex) {
- this.pointList[this.curIndex].x = event.x;
- this.pointList[this.curIndex].y = event.y;
- }
- this.update()
- } else {
- // return super.onMouseMove(event)
- }
- return true;
- } // Function onMouseMove()
- /**
- * 鼠标抬起事件
- *
- * @param event 事件参数
- * @return boolean
- */
- onMouseUp(event: SMouseEvent): boolean {
- if (this.status == SItemStatus.Edit) {
- if (-1 != this.curIndex) {
- const pos = new SPoint(this.pointList[this.curIndex].x, this.pointList[this.curIndex].y)
- this.recordAction(SGraphPointListUpdate, [this.pointList, this.curPoint, pos, this.curIndex])
- }
- this.curIndex = -1;
- this.curPoint = null;
- } else {
- // return super.onMouseUp(event)
- }
- return true;
- } // Function onMouseUp()
- /**
- * 适配事件
- *
- * @param event 事件参数
- * @return boolean
- */
- onResize(event: SMouseEvent): boolean {
- return true;
- } // Function onResize()
- /**
- * 取消操作
- *
- * @param painter painter对象
- */
- cancelOperate(): void {
- // 当状态为展示状态
- if (this.status == SItemStatus.Create) {
- // 闭合多边形
- this.parent = null
- } else if (this.status == SItemStatus.Edit) {
- // 编辑状态
- this.status = SItemStatus.Normal
- }
- this.update()
- } // Function cancelOperate()
- /**
- * Item对象边界区域
- *
- * @return SRect
- */
- boundingRect(): SRect {
- if (this.pointList.length) {
- this.minX = this.pointList[0].x;
- this.maxX = this.pointList[0].x;
- this.minY = this.pointList[0].y;
- this.maxY = this.pointList[0].y;
- this.pointList.forEach(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 SRect(
- this.minX,
- this.minY,
- this.maxX - this.minX,
- this.maxY - this.minY
- );
- } // Function boundingRect()
- /**
- * 判断点是否在区域内
- *
- * @param x
- * @param y
- */
- contains(x: number, y: number): boolean {
- let arr = this.pointList;
- if (arr.length < 3 || !SPolygonUtil.pointIn(x, y, arr)) {
- return false;
- }
- return true;
- } // Function contains()
- /**
- * Item绘制操作
- *
- * @param painter painter对象
- */
- onDraw(painter: SPainter): void {
- this.scenceLen = painter.toPx(this.len)
- // 当状态为展示状态
- if (this.status == SItemStatus.Normal) {
- // 闭合多边形
- this.drawShowPolygon(painter, this.pointList);
- } else if (this.status == SItemStatus.Create) {
- // 创建状态
- this.drawCreatePolygon(painter, this.pointList)
- } else {
- // 编辑状态
- this.drawEditPolygon(painter, this.pointList);
- }
- } // Function onDraw()
- }
|