haojianlong 4 лет назад
Родитель
Сommit
adefbd25cb

+ 567 - 0
docs/.vuepress/components/example/graph/scene/SEditPolygon.vue

@@ -0,0 +1,567 @@
+<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 "@persagy-web/graph/";
+import {
+  SColor,
+  SLineCapStyle,
+  SPainter,
+  SPath2D,
+  SPoint,
+  SPolygonUtil,
+  SRect,
+  SLine
+} from "@persagy-web/draw";
+import { SRelationState } from "@persagy-web/big/lib/enums/SRelationState";
+import { SMathUtil } from "@persagy-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>

+ 2 - 2
docs/dev/graph/scene/items/editPolygon.md

@@ -3,7 +3,7 @@
 [[toc]]
 :::
 
-example-graph-scene-SEditPolygon
+<example-graph-scene-SEditPolygon />
 
 ::: tip 注
 1、可以通过双击table在编辑状态和展示状态来回切换,<br/>
@@ -14,4 +14,4 @@ example-graph-scene-SEditPolygon
 
 ::: details 查看代码
 @/docs/.vuepress/components/example/graph/scene/SEditPolygon.vue
-:::
+:::