Ver código fonte

Merge branch 'master' of http://39.106.8.246:3003/doc/persagy-web-doc

haojianlong 4 anos atrás
pai
commit
aff3774ded

+ 68 - 44
docs/.vuepress/components/edit/items/editPolygon/editPolygon.vue

@@ -1,9 +1,18 @@
 <template>
   <div class="edit-line">
+    <!-- 所有按钮 -->
     <div class="btn-list">
-      <el-button :class="[cmdStatus=='create' ? 'heightLight' : '']" size="small" @click="create">画线</el-button>
+      <el-button
+        :class="[cmdStatus=='create' ? 'heightLight' : '']"
+        size="small"
+        @click="create"
+      >创建多边形</el-button>
       <el-tooltip class="item" effect="dark" content="双击 item 也可进入编辑状态" placement="top-start">
-        <el-button :class="[cmdStatus=='edit' ? 'heightLight' : '']" size="small" @click="edit">编辑</el-button>
+        <el-button
+          :class="[cmdStatus=='edit' ? 'heightLight' : '']"
+          size="small"
+          @click="edit"
+        >编辑多边形</el-button>
       </el-tooltip>
 
       <el-button
@@ -16,12 +25,12 @@
           :class="[cmdStatus=='eqDrawLine' ? 'heightLight' : '']"
           size="small"
           @click="eqDrawLine"
-        >垂直水平划线</el-button>
+        >垂直水平绘制</el-button>
       </el-tooltip>
     </div>
     <div class="content">
       <div class="left">
-        <canvas id="edit_line" width="700" height="460" tabindex="0" />
+        <canvas id="edit_polygon" width="700" height="460" tabindex="0" />
       </div>
       <div class="line-property">
         <el-card shadow="always">
@@ -29,7 +38,7 @@
             <span>属性修改</span>
           </div>
           <div class="always-item">
-            <span>线宽:</span>
+            <span>边框宽:</span>
             <el-input-number
               size="small"
               v-model="lineWidth"
@@ -59,6 +68,10 @@
             <span>线颜色:</span>
             <el-color-picker v-model="lineColor" @change="changeColor" show-alpha></el-color-picker>
           </div>
+          <div class="always-item">
+            <span>填充色:</span>
+            <el-color-picker v-model="fillColor" @change="changeFillColor" show-alpha></el-color-picker>
+          </div>
         </el-card>
       </div>
     </div>
@@ -68,22 +81,23 @@
 <script>
 import { SGraphScene, SGraphView, SLineStyle } from "@persagy-web/graph/";
 import { SItemStatus } from "@persagy-web/big/lib/enums/SItemStatus";
-import { SPoint } from "@persagy-web/draw/";
-import { EditLineItem } from "./../../../../../guides/edit/items/src/EditLineItem";
+import { SPoint ,SColor} from "@persagy-web/draw/";
+//注: 开发者引入 EditPolygonItem 包为: import {EditPolygonItem} from "@persagy-web/edit/";
+import { EditPolygonItem } from "./../../../../../guides/edit/items/src/EditPolygonItem";
 import { hexify } from "./../../../../public/until/rgbaUtil";
-//注: 开发者引入 SWallItem 包为: import {SWallItem} from "@persagy-web/edit/";
 export default {
-  name: "editLine",
+  name: "editpolygon",
   data() {
     return {
-      scene: null,
-      view: null,
-      isCreated: false, //是否创建完成
-      cmdStatus: "", //选中状态
-      lineItem: null, //存放创建的Item
-      lineWidth: 1,
-      lineColor: "",
-      lineType: "",
+      scene: null,       //场景
+      view: null,        //view实例
+      isCreated: false,  //是否创建完成
+      cmdStatus: "",     //选中状态
+      polygonItem: null, //存放创建的Item
+      lineWidth: 1,      //border线宽
+      lineColor: "",     //border线颜色
+      fillColor:"",      //填充色
+      lineType: "",      //border线类型
       options: [
         {
           value: "Solid",
@@ -101,7 +115,7 @@ export default {
     };
   },
   mounted() {
-    this.view = new SGraphView("edit_line");
+    this.view = new SGraphView("edit_polygon");
     this.scene = new SGraphScene();
     this.view.scene = this.scene;
   },
@@ -109,27 +123,28 @@ export default {
     create() {
       this.cmdStatus = "create";
       this.scene.root.children = [];
-      this.lineItem = new EditLineItem(null, []);
-      this.lineItem.status = SItemStatus.Create;
-      this.lineItem.connect("finishCreated", this, this.finishCreated);
-      this.scene.addItem(this.lineItem);
-      this.scene.grabItem = this.lineItem;
+      this.polygonItem = new EditPolygonItem(null);
+      this.polygonItem.status = SItemStatus.Create;
+      this.polygonItem.connect("finishCreated", this, this.finishCreated);
+      this.scene.addItem(this.polygonItem);
+      this.scene.grabItem = this.polygonItem;
       this.view.update();
     },
     deleteItem() {
       this.cmdStatus = "";
-      this.scene.removeItem(this.lineItem);
-      this.lineItem = null;
+      this.scene.removeItem(this.polygonItem);
+      this.polygonItem = null;
       this.view.update();
     },
     edit() {
-      if (this.lineItem) {
-        if (this.lineItem.status == SItemStatus.Normal) {
-          this.scene.grabItem = this.lineItem;
-          this.lineItem.status = SItemStatus.Edit;
+      if (this.polygonItem) {
+        if (this.polygonItem.status == SItemStatus.Normal) {
+          this.scene.grabItem = this.polygonItem;
+          this.polygonItem.status = SItemStatus.Edit;
+          // this.polygonItem.verAndLeve = false;
           this.cmdStatus = "edit";
         } else {
-          this.lineItem.status = SItemStatus.Normal;
+          this.polygonItem.status = SItemStatus.Normal;
           this.scene.grabItem = null;
           this.cmdStatus = "";
         }
@@ -138,32 +153,40 @@ export default {
     eqDrawLine() {
       this.cmdStatus = "eqDrawLine";
       this.scene.root.children = [];
-      this.lineItem = new EditLineItem(null, []);
-      this.lineItem.verAndLeve = true;
-      this.lineItem.status = SItemStatus.Create;
-      this.lineItem.connect("finishCreated", this, this.finishCreated);
-      this.scene.addItem(this.lineItem);
-      this.scene.grabItem = this.lineItem;
+      this.polygonItem = new EditPolygonItem(null, []);
+      this.polygonItem.verAndLeve = true;
+      this.polygonItem.status = SItemStatus.Create;
+      this.polygonItem.connect("finishCreated", this, this.finishCreated);
+      this.polygonItem.moveable = true;
+      this.scene.addItem(this.polygonItem);
+      this.scene.grabItem = this.polygonItem;
       this.view.update();
     },
     // 改变线宽属性
     changeLineWidth(val) {
-      if (this.lineItem) {
+      if (this.polygonItem) {
         this.lineWidth = val;
-        this.lineItem.lineWidth = val;
+        this.polygonItem.lineWidth = val;
       }
     },
     // 改变颜色
     changeColor(val) {
-      if (this.lineItem) {
+      if (this.polygonItem) {
         this.lineColor = hexify(val);
-        this.lineItem.strokeColor = this.lineColor;
+        this.polygonItem.strokeColor = new SColor(this.lineColor);
+      }
+    },
+     // 改变填充颜色
+    changeFillColor(val) {
+      if (this.polygonItem) {
+        this.fillColor = hexify(val);
+        this.polygonItem.fillColor = new SColor(this.lineColor);
       }
     },
     //改变线得类型
     changeType(val) {
-      if (this.lineItem) {
-        this.lineItem.lineStyle = SLineStyle[val];
+      if (this.polygonItem) {
+        this.polygonItem.lineStyle = SLineStyle[val];
       }
     },
     // 完成创建后的回调
@@ -172,11 +195,12 @@ export default {
     }
   },
   watch: {
-    lineItem(val) {
+    polygonItem(val) {
       if (val) {
         this.lineWidth = val.lineWidth; // 线宽
         this.lineStyle = val.lineStyle; // 线条样式
         this.lineColor = val.strokeColor.value; // 线条填充色
+        this.fillColor = val.fillColor.value; // 线条填充色
         this.lineType = this.options[val.lineStyle].value;
       } else {
         this.lineWidth = 0;
@@ -199,7 +223,7 @@ export default {
     .line-property {
       width: 300px;
       margin-top: 20px;
-      .always{
+      .always {
         width: 100%;
         height: 100%;
       }

+ 241 - 0
docs/.vuepress/components/edit/items/editpolyline/editpolyline.vue

@@ -0,0 +1,241 @@
+<template>
+  <div class="edit-line">
+    <!-- 所有按钮 -->
+    <div class="btn-list">
+      <el-button
+        :class="[cmdStatus=='create' ? 'heightLight' : '']"
+        size="small"
+        @click="create"
+      >创建多边形</el-button>
+      <el-tooltip class="item" effect="dark" content="双击 item 也可进入编辑状态" placement="top-start">
+        <el-button
+          :class="[cmdStatus=='edit' ? 'heightLight' : '']"
+          size="small"
+          @click="edit"
+        >编辑多边形</el-button>
+      </el-tooltip>
+
+      <el-button
+        :class="[cmdStatus=='deleteItem' ? 'heightLight' : '']"
+        size="small"
+        @click="deleteItem"
+      >删除</el-button>
+      <el-tooltip class="item" effect="dark" content="长按 Shoft 配合左键也可触发该功能" placement="top-start">
+        <el-button
+          :class="[cmdStatus=='eqDrawLine' ? 'heightLight' : '']"
+          size="small"
+          @click="eqDrawLine"
+        >垂直水平绘制</el-button>
+      </el-tooltip>
+    </div>
+    <div class="content">
+      <div class="left">
+        <canvas id="edit_polygon" width="700" height="460" tabindex="0" />
+      </div>
+      <div class="line-property">
+        <el-card shadow="always">
+          <div slot="header" class="clearfix">
+            <span>属性修改</span>
+          </div>
+          <div class="always-item">
+            <span>边框宽:</span>
+            <el-input-number
+              size="small"
+              v-model="lineWidth"
+              @change="changeLineWidth"
+              :min="1"
+              :max="50"
+            ></el-input-number>
+          </div>
+          <div class="always-item">
+            <span>线类型:</span>
+            <el-select
+              style="width:130px"
+              size="small"
+              v-model="lineType"
+              @change="changeType"
+              placeholder="请选择"
+            >
+              <el-option
+                v-for="item in options"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              ></el-option>
+            </el-select>
+          </div>
+          <div class="always-item">
+            <span>线颜色:</span>
+            <el-color-picker v-model="lineColor" @change="changeColor" show-alpha></el-color-picker>
+          </div>
+          <!-- <div class="always-item">
+            <span>填充色:</span>
+            <el-color-picker v-model="fillColor" @change="changeFillColor" show-alpha></el-color-picker>
+          </div> -->
+        </el-card>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { SGraphScene, SGraphView, SLineStyle } from "@persagy-web/graph/";
+import { SItemStatus } from "@persagy-web/big/lib/enums/SItemStatus";
+import { SPoint ,SColor} from "@persagy-web/draw/";
+//注: 开发者引入 EditPolygonItem 包为: import {EditPolygonItem} from "@persagy-web/edit/";
+import { EditPolylineItem } from "./../../../../../guides/edit/items/src/EditPolylineItem";
+import { hexify } from "./../../../../public/until/rgbaUtil";
+export default {
+  name: "EditPolylineItem",
+  data() {
+    return {
+      scene: null,       //场景
+      view: null,        //view实例
+      isCreated: false,  //是否创建完成
+      cmdStatus: "",     //选中状态
+      polylineItem: null, //存放创建的Item
+      lineWidth: 1,      //border线宽
+      lineColor: "",     //border线颜色
+      fillColor:"",      //填充色
+      lineType: "",      //border线类型
+      options: [
+        {
+          value: "Solid",
+          label: "实线"
+        },
+        {
+          value: "Dashed",
+          label: "虚线"
+        },
+        {
+          value: "Dotted",
+          label: "点"
+        }
+      ]
+    };
+  },
+  mounted() {
+    this.view = new SGraphView("edit_polygon");
+    this.scene = new SGraphScene();
+    this.view.scene = this.scene;
+  },
+  methods: {
+    create() {
+      this.cmdStatus = "create";
+      this.scene.root.children = [];
+      this.polylineItem = new EditPolylineItem(null,[]);
+      this.polylineItem.status = SItemStatus.Create;
+      this.polylineItem.connect("finishCreated", this, this.finishCreated);
+      this.scene.addItem(this.polylineItem);
+      this.scene.grabItem = this.polylineItem;
+      this.view.update();
+    },
+    deleteItem() {
+      this.cmdStatus = "";
+      this.scene.removeItem(this.polylineItem);
+      this.polylineItem = null;
+      this.view.update();
+    },
+    edit() {
+      if (this.polylineItem) {
+        if (this.polylineItem.status == SItemStatus.Normal) {
+          this.scene.grabItem = this.polylineItem;
+          this.polylineItem.status = SItemStatus.Edit;
+          // this.polylineItem.verAndLeve = false;
+          this.cmdStatus = "edit";
+        } else {
+          this.polylineItem.status = SItemStatus.Normal;
+          this.scene.grabItem = null;
+          this.cmdStatus = "";
+        }
+      }
+    },
+    eqDrawLine() {
+      this.cmdStatus = "eqDrawLine";
+      this.scene.root.children = [];
+      this.polylineItem = new EditPolylineItem(null, []);
+      this.polylineItem.verAndLeve = true;
+      this.polylineItem.status = SItemStatus.Create;
+      this.polylineItem.connect("finishCreated", this, this.finishCreated);
+      this.polylineItem.moveable = true;
+      this.scene.addItem(this.polylineItem);
+      this.scene.grabItem = this.polylineItem;
+      this.view.update();
+    },
+    // 改变线宽属性
+    changeLineWidth(val) {
+      if (this.polylineItem) {
+        this.lineWidth = val;
+        this.polylineItem.lineWidth = val;
+      }
+    },
+    // 改变颜色
+    changeColor(val) {
+      if (this.polylineItem) {
+        this.lineColor = hexify(val);
+        this.polylineItem.strokeColor = new SColor(this.lineColor);
+      }
+    },
+     // 改变填充颜色
+    changeFillColor(val) {
+      if (this.polylineItem) {
+        this.fillColor = hexify(val);
+        this.polylineItem.fillColor = new SColor(this.lineColor);
+      }
+    },
+    //改变线得类型
+    changeType(val) {
+      if (this.polylineItem) {
+        this.polylineItem.lineStyle = SLineStyle[val];
+      }
+    },
+    // 完成创建后的回调
+    finishCreated() {
+      this.cmdStatus = "";
+    }
+  },
+  watch: {
+    polylineItem(val) {
+      if (val) {
+        this.lineWidth = val.lineWidth; // 线宽
+        this.lineColor = val.strokeColor.value; // 线条填充色
+        this.lineType = this.options[val.lineStyle].value;
+      } else {
+        this.lineWidth = 0;
+      }
+    }
+  }
+};
+</script>
+
+<style scoped lang="less">
+.edit-line {
+  width: 100%;
+  height: 500px;
+  .content {
+    display: flex;
+    justify-content: flex-start;
+    .left {
+      margin-right: 20px;
+    }
+    .line-property {
+      width: 300px;
+      margin-top: 20px;
+      .always {
+        width: 100%;
+        height: 100%;
+      }
+      .always-item {
+        display: flex;
+        margin-top: 10px;
+        justify-content: space-between;
+      }
+    }
+  }
+  .heightLight {
+    color: #409eff;
+    border-color: #c6e2ff;
+    background-color: #ecf5ff;
+  }
+}
+</style>

+ 73 - 0
docs/guides/edit/items/editPolygon.md

@@ -0,0 +1,73 @@
+# 多边形编辑类 EditPolygonItem 示例
+::: details 目录
+[[toc]]
+:::
+
+## 绘制示例
+
+<edit-items-editpolygon-editpolygon/>
+
+::: details 示例代码
+
+<<< @/docs/.vuepress/components/edit/items/editpolygon/editpolygon.vue
+
+:::
+
+## 源代码
+
+::: details 查看代码
+
+<<< @/docs/guides/edit/items/src/EditPolygonItem.ts
+
+:::
+
+## 代码说明
+
+### 1 当 EditPolygonItem 为编辑状态时,需要将 EditPolygonItem 赋给 grabItem
+``` js {4}
+ // 编辑状态时的 LineItem
+ this.polygonItem = new EditPolygonItem(null);
+ this.polygonItem.status = SItemStatus.Create;
+ this.scene.grabItem = this.polygonItem;
+```
+### 2 当 EditPolygonItem 为正常状态时,需要将 grabItem 置为 null
+``` js {4}
+ // 正常状态时的 LineItem
+ this.polygonItem = new EditPolygonItem(null);
+ this.polygonItem.status = SItemStatus.Normal;
+ this.scene.grabItem = null;
+```
+### 3 当 EditPolygonItem 为试图垂直水平绘制时需要修改 verAndLeve 属性
+``` js {3}
+ // 编辑状态时的 LineItem
+ this.polygonItem = new EditPolygonItem(null,);
+ this.polygonItem.status = SItemStatus.Create;
+ this.polygonItem.verAndLeve = true;
+ this.scene.grabItem = this.polygonItem;
+```
+### 4 当 EditPolygonItem 修改属性但是画板尚未变化时需要刷新
+``` js {4}
+ // 编辑状态时的 LineItem
+ this.polygonItem = new EditPolygonItem(null);
+ this.polygonItem.status = SItemStatus.Create;
+ this.view.update();
+```
+### 5 当 EditPolygonItem 需要拖动时设置 moveable = true
+``` js {4}
+ // 编辑状态时的 LineItem
+  this.polygonItem = new EditPolygonItem(null);
+  this.polygonItem.status = SItemStatus.Create;
+  this.polygonItem.moveable = true;
+```
+### 6 当 EditPolygonItem 绘制完成后的回调函数为 finishCreated
+``` js {4}
+ // 编辑状态时的 LineItem
+  this.polygonItem = new EditPolygonItem(null);
+  this.polygonItem.status = SItemStatus.Create;
+  this.polygonItem.connect("finishCreated", this, this.finishCreated);
+  this.polygonItem.moveable = true;
+  methods:{
+      finishCreated(){
+      }
+  }
+```

+ 0 - 8
docs/guides/edit/items/editPolygonItem.md

@@ -1,8 +0,0 @@
-# 多边形编辑类 EditPolygonItem 示例
-::: details 目录
-[[toc]]
-:::
-
-## 绘制示例
-
-<edit-items-editPolygon-editPolygon />

+ 61 - 0
docs/guides/edit/items/editPolyline.md

@@ -0,0 +1,61 @@
+# 折线编辑类 EditPolylineItem 示例
+::: details 目录
+[[toc]]
+:::
+
+## 绘制示例
+
+<edit-items-editpolyline-editpolyline/>
+
+::: details 示例代码
+
+<<< @/docs/.vuepress/components/edit/items/editpolyline/editpolyline.vue
+
+:::
+
+## 源代码
+
+::: details 查看代码
+
+<<< @/docs/guides/edit/items/src/EditLineItem.ts
+
+:::
+
+## 代码说明
+
+### 1 当 EditPolylineItem 为编辑状态时,需要将 EditPolylineItem 赋给 grabItem
+``` js {4}
+ // 编辑状态时的 LineItem
+ this.polylineItem = new EditPolylineItem(null);
+ this.polylineItem.status = SItemStatus.Create;
+ this.scene.grabItem = this.polylineItem;
+```
+### 2 当 EditPolylineItem 为正常状态时,需要将 grabItem 置为 null
+``` js {4}
+ // 正常状态时的 LineItem
+ this.polylineItem = new EditPolylineItem(null);
+ this.polylineItem.status = SItemStatus.Normal;
+ this.scene.grabItem = null;
+```
+### 3 当 EditPolylineItem 为试图垂直水平绘制时需要修改 verAndLeve 属性
+``` js {3}
+ // 编辑状态时的 LineItem
+ this.polylineItem = new EditPolylineItem(null,);
+ this.polylineItem.status = SItemStatus.Create;
+ this.polylineItem.verAndLeve = true;
+ this.scene.grabItem = this.polylineItem;
+```
+### 4 当 EditPolylineItem 修改属性但是画板尚未变化时需要刷新
+``` js {4}
+ // 编辑状态时的 LineItem
+ this.polylineItem = new EditPolylineItem(null);
+ this.polylineItem.status = SItemStatus.Create;
+ this.view.update();
+```
+### 5 当 EditPolylineItem 需要拖动时设置 moveable = true
+``` js {4}
+ // 编辑状态时的 LineItem
+  this.polylineItem = new EditPolylineItem(null);
+  this.polylineItem.status = SItemStatus.Create;
+  this.polylineItem.moveable = true;
+```

+ 17 - 9
docs/guides/edit/items/src/EditPolygonItem.ts

@@ -15,15 +15,15 @@ import {
     SPolygonUtil,
     SRect
 } from "@persagy-web/draw";
-import { SItemStatus } from "..";
-import { SMathUtil } from "../utils/SMathUtil";
+import { SItemStatus } from "@persagy-web/big";
+import { SMathUtil } from "@persagy-web/big/lib/utils/SMathUtil";
 
 /**
  * 编辑多边形
  *
  * @author  韩耀龙
  */
-export class SPolygonItem extends SGraphItem {
+export class EditPolygonItem extends SGraphItem {
     /** X坐标最小值  */
     private minX = Number.MAX_SAFE_INTEGER;
     /** X坐标最大值  */
@@ -44,7 +44,15 @@ export class SPolygonItem extends SGraphItem {
         this.pointList = arr;
         this.update();
     }
-
+    /** 是否垂直水平绘制   */
+    private _verAndLeve: Boolean = false;
+    get verAndLeve(): Boolean {
+        return this._verAndLeve;
+    }
+    set verAndLeve(bool: Boolean) {
+        this._verAndLeve = bool;
+        this.update();
+    }
     // 当前状态
     protected _status: number = SItemStatus.Normal;
     // 获取当前状态
@@ -390,9 +398,9 @@ export class SPolygonItem extends SGraphItem {
             // 2判断是否点击在多边形得边上
             if (-1 == lenIndex) {
                 let len = SMathUtil.pointToLine(
-                        new SPoint(event.x, event.y),
-                        new SLine(this.pointList[0], this.pointList[1])
-                    ),
+                    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++) {
@@ -553,7 +561,7 @@ export class SPolygonItem extends SGraphItem {
      * @return	boolean
      */
     onMouseDown(event: SMouseEvent): boolean {
-        if (event.shiftKey) {
+        if (event.shiftKey || this.verAndLeve) {
             event = this.compare(event);
         }
         // 如果状态为编辑状态则添加点
@@ -618,7 +626,7 @@ export class SPolygonItem extends SGraphItem {
      */
 
     onMouseMove(event: SMouseEvent): boolean {
-        if (event.shiftKey) {
+        if (event.shiftKey || this.verAndLeve) {
             event = this.compare(event);
         }
         if (this.status == SItemStatus.Create) {

+ 601 - 0
docs/guides/edit/items/src/EditPolylineItem.ts

@@ -0,0 +1,601 @@
+import { SColor, SLine, SPainter, SPoint, SRect } from "@persagy-web/draw";
+import { SKeyCode, SMouseEvent, SUndoStack } from "@persagy-web/base";
+import { SItemStatus } from "@persagy-web/big";;
+import { SMathUtil } from "@persagy-web/big/lib/utils/SMathUtil";;
+import {
+    SGraphItem,
+    SGraphPointListDelete,
+    SGraphPointListInsert,
+    SGraphPointListUpdate,
+    SLineStyle
+} from "@persagy-web/graph/lib";
+
+/**
+ * 直线item
+ *
+ * */
+
+export class EditPolylineItem 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;
+    /** 折点信息    */
+    pointList: SPoint[] = [];
+    /** 是否绘制完成  */
+    _status: SItemStatus = SItemStatus.Normal;
+    get status(): SItemStatus {
+        return this._status;
+    }
+    set status(v: SItemStatus) {
+        this._status = v;
+        this.undoStack.clear();
+        this.update();
+    }
+    /** 鼠标移动时的点 */
+    private lastPoint: SPoint | null = null;
+    /** 线条颜色    */
+    _strokeColor: SColor = SColor.Black;
+    get strokeColor(): SColor {
+        return this._strokeColor;
+    }
+    set strokeColor(v: SColor) {
+        this._strokeColor = v;
+        this.update();
+    }
+    /** 填充色 */
+    _fillColor: SColor = new SColor("#2196f3");
+    get fillColor(): SColor {
+        return this._fillColor;
+    }
+    set fillColor(v: SColor) {
+        this._fillColor = v;
+        this.update();
+    }
+    /** 边框样式 */
+    _lineStyle: SLineStyle = SLineStyle.Solid;
+    get lineStyle(): SLineStyle {
+        return this._lineStyle;
+    }
+    set lineStyle(v: SLineStyle) {
+        this._lineStyle = v;
+        this.update();
+    }
+    /** 线条宽度    */
+    _lineWidth: number = 1;
+    get lineWidth(): number {
+        return this._lineWidth;
+    }
+    set lineWidth(v: number) {
+        this._lineWidth = v;
+        this.update();
+    }
+    /** 是否垂直水平绘制   */
+    private _verAndLeve: Boolean = false;
+    get verAndLeve(): Boolean {
+        return this._verAndLeve;
+    }
+    set verAndLeve(bool: Boolean) {
+        this._verAndLeve = bool;
+        this.update();
+    }
+    /** 全局灵敏度   */
+    dis: number = 10;
+    /** 灵敏度转换为场景长度  */
+    private sceneDis: number = 10;
+    /** 当前点索引   */
+    private curIndex: number = -1;
+    /** 当前点索引   */
+    private curPoint: SPoint | null = null;
+    /** undo/redo堆栈 */
+    private undoStack: SUndoStack = new SUndoStack();
+
+    /**
+     * 构造函数
+     *
+     * @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);
+            this.recordAction(SGraphPointListInsert, [
+                this.pointList,
+                p,
+                index
+            ]);
+        } else {
+            this.pointList.push(p);
+            this.recordAction(SGraphPointListInsert, [this.pointList, 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   删除点
+     * */
+    deletePoint(index: number): void {
+        if (this.canHandle(index) && this.pointList.length > 2) {
+            const p = new SPoint(
+                this.pointList[this.curIndex].x,
+                this.pointList[this.curIndex].y
+            );
+            this.pointList.splice(index, 1);
+            this.recordAction(SGraphPointListDelete, [
+                this.pointList,
+                p,
+                index
+            ]);
+            this.curIndex = -1;
+            this.curPoint = null;
+            this.update();
+        }
+    } // Function deletePoint
+
+    /**
+     * 鼠标按下事件
+     *
+     * @param   event   鼠标事件
+     * @return  boolean 是否处理事件
+     * */
+    onMouseDown(event: SMouseEvent): boolean {
+        this.curIndex = -1;
+        this.curPoint = null;
+        if (event.shiftKey || this.verAndLeve) {
+            event = this.compare(event);
+        }
+        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 (this.curIndex < 0) {
+                    this.findAddPos(new SPoint(event.x, event.y));
+                }
+                // 删除点
+                if (event.altKey && this.canHandle(this.curIndex)) {
+                    this.deletePoint(this.curIndex);
+                }
+                this.update();
+                return true;
+            } else {
+                return super.onMouseDown(event);
+            }
+        }
+        return super.onMouseDown(event);
+    } // Function onMouseDown()
+
+    /**
+     * 鼠标移动事件
+     *
+     * @param   event   鼠标事件
+     * @return  boolean 是否处理事件
+     * */
+    onMouseMove(event: SMouseEvent): boolean {
+        if (event.shiftKey || this.verAndLeve) {
+            event = this.compare(event);
+        }
+        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 (event.buttons == 1) {
+                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 {
+        if (this.status == SItemStatus.Edit) {
+            if (this.curIndex > -1) {
+                const p = new SPoint(
+                    this.pointList[this.curIndex].x,
+                    this.pointList[this.curIndex].y
+                );
+                this.recordAction(SGraphPointListUpdate, [
+                    this.pointList,
+                    this.curPoint,
+                    p,
+                    this.curIndex
+                ]);
+            }
+        } else if (this.status == SItemStatus.Normal) {
+            this.moveToOrigin(this.x, this.y);
+            return super.onMouseUp(event);
+        }
+        return true;
+    } // Function onMouseUp()
+
+    /**
+     * 鼠标双击事件
+     *
+     * @param	event         事件参数
+     * @return	boolean
+     */
+    onDoubleClick(event: SMouseEvent): boolean {
+        if (this.status == SItemStatus.Normal) {
+            this.status = SItemStatus.Edit;
+            this.grabItem(this);
+        } else if (this.status == SItemStatus.Edit) {
+            this.status = SItemStatus.Normal;
+            this.releaseItem();
+        } else if (this.status == SItemStatus.Create) {
+            if (this.pointList.length > 1) {
+                this.status = SItemStatus.Normal;
+                this.releaseItem();
+                this.$emit("finishCreated");
+            }
+        }
+        this.$emit("onDoubleClick", event);
+        return true;
+    } // Function onDoubleClick()
+
+    /***
+     * 键盘按键弹起事件
+     *
+     * @param	event         事件参数
+     */
+    onKeyUp(event: KeyboardEvent): void {
+        if (event.keyCode == SKeyCode.Enter) {
+            if (this.pointList.length > 1) {
+                if (this.status == SItemStatus.Create) {
+                    this.$emit("finishCreated");
+                }
+                this.status = SItemStatus.Normal;
+                this.releaseItem();
+            }
+        }
+        // delete删除点
+        if (
+            event.keyCode == SKeyCode.Delete &&
+            this.status == SItemStatus.Edit
+        ) {
+            this.deletePoint(this.curIndex);
+        }
+    } // Function onKeyUp()
+
+    /**
+     * 移动后处理所有坐标,并肩原点置为场景原点
+     *
+     * @param   x   x坐标
+     * @param   y   y坐标
+     * */
+    moveToOrigin(x: number, y: number): void {
+        super.moveToOrigin(x, y);
+        this.pointList = this.pointList.map(t => {
+            t.x = t.x + x;
+            t.y = t.y + y;
+            return t;
+        });
+        this.x = 0;
+        this.y = 0;
+    } // Function moveToOrigin()
+
+    /**
+     * 获取点击点与点集中距离最近点
+     *
+     * @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;
+                this.curPoint = new SPoint(
+                    this.pointList[this.curIndex].x,
+                    this.pointList[this.curIndex].y
+                );
+            }
+        }
+    } // Function findNearestPoint()
+
+    /**
+     * 计算增加点的位置
+     *
+     * @param   p   鼠标点击点
+     * */
+    findAddPos(p: SPoint): void {
+        let len = SMathUtil.pointToLine(
+            p,
+            new SLine(this.pointList[0], this.pointList[1])
+        ),
+            index = 0;
+        if (this.pointList.length > 2) {
+            for (let i = 1; i < this.pointList.length - 1; i++) {
+                let dis = SMathUtil.pointToLine(
+                    p,
+                    new SLine(this.pointList[i], this.pointList[i + 1])
+                );
+                if (dis.MinDis < len.MinDis) {
+                    len = dis;
+                    index = i;
+                }
+            }
+        }
+        if (len.MinDis < this.sceneDis) {
+            if (len.Point) {
+                this.addPoint(len.Point, index + 1);
+            }
+        }
+    } // Function findAddPos()
+
+    /**
+     * shift垂直水平创建或编辑
+     *
+     * @param   event   事件
+     * */
+    compare(event: SMouseEvent): SMouseEvent {
+        if (this.pointList.length) {
+            let last = new SPoint(event.x, event.y);
+            if (this.status == SItemStatus.Create) {
+                last = this.pointList[this.pointList.length - 1];
+            } else if (this.status == SItemStatus.Edit) {
+                if (this.curIndex > 1) {
+                    last = this.pointList[this.curIndex - 1];
+                }
+            }
+            const dx = Math.abs(event.x - last.x);
+            const dy = Math.abs(event.y - last.y);
+            if (dy > dx) {
+                event.x = last.x;
+            } else {
+                event.y = last.y;
+            }
+        }
+        return event;
+    } // Function compare()
+
+    /**
+     * 记录相关动作并推入栈中
+     *
+     * @param	SGraphCommand   相关命令类
+     * @param	any             对应传入参数
+     */
+    protected recordAction(SGraphCommand: any, any: any[]): void {
+        // 记录相关命令并推入堆栈中
+        const command = new SGraphCommand(this.scene, this, ...any);
+        this.undoStack.push(command);
+    } // Function recordAction()
+
+    /**
+     * 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
+     * @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()
+
+    /**
+     * 撤销操作
+     *
+     */
+    undo(): void {
+        if (this._status != SItemStatus.Normal) {
+            this.undoStack.undo();
+        }
+    } // Function undo()
+
+    /**
+     * 重做操作
+     *
+     */
+    redo(): void {
+        if (this._status != SItemStatus.Normal) {
+            this.undoStack.redo();
+        }
+    } // Function redo()
+
+    /**
+     * 取消操作执行
+     *
+     * */
+    cancelOperate(): void {
+        if (this.status == SItemStatus.Create) {
+            this.parent = null;
+            this.releaseItem();
+        } else if (this.status == SItemStatus.Edit) {
+            this.status = SItemStatus.Normal;
+            this.releaseItem();
+        }
+    } // Function cancelOperate()
+
+    /**
+     * 绘制基本图形
+     * */
+    drawBaseLine(painter: SPainter): void {
+        // 绘制基本图形
+        painter.pen.color = this.strokeColor;
+        if (this.lineStyle == SLineStyle.Dashed) {
+            painter.pen.lineDash = [
+                painter.toPx(this.lineWidth * 3),
+                painter.toPx(this.lineWidth * 7)
+            ];
+        } else if (this.lineStyle == SLineStyle.Dotted) {
+            painter.pen.lineDash = [
+                painter.toPx(this.lineWidth),
+                painter.toPx(this.lineWidth)
+            ];
+        }
+        painter.drawPolyline(this.pointList);
+    } // Function drawBaseLine()
+
+    /**
+     * Item绘制操作
+     *
+     * @param   painter painter对象
+     */
+    onDraw(painter: SPainter): void {
+        // 缓存场景长度
+        this.sceneDis = painter.toPx(this.dis);
+        // 创建状态
+        painter.pen.lineWidth = painter.toPx(this.lineWidth);
+        if (this.status == SItemStatus.Create && this.lastPoint) {
+            // 绘制基本图形
+            this.drawBaseLine(painter);
+            painter.drawLine(
+                this.pointList[this.pointList.length - 1],
+                this.lastPoint
+            );
+            // 编辑状态
+            this.pointList.forEach((t, i): void => {
+                painter.brush.color = SColor.White;
+                if (i == this.curIndex) {
+                    painter.brush.color = this.fillColor;
+                }
+                painter.drawCircle(t.x, t.y, painter.toPx(5));
+            });
+        } else if (this.status == SItemStatus.Edit) {
+            // 绘制基本图形
+            this.drawBaseLine(painter);
+            // 编辑状态
+            this.pointList.forEach((t, i): void => {
+                painter.brush.color = SColor.White;
+                if (i == this.curIndex) {
+                    painter.brush.color = this.fillColor;
+                }
+                painter.drawCircle(t.x, t.y, painter.toPx(5));
+            });
+        } else {
+            // 查看状态
+            if (this.selected) {
+                painter.pen.lineWidth = painter.toPx(this.lineWidth * 2);
+                painter.shadow.shadowBlur = 10;
+                painter.shadow.shadowColor = new SColor(`#00000033`);
+                painter.shadow.shadowOffsetX = 5;
+                painter.shadow.shadowOffsetY = 5;
+            }
+            // 绘制基本图形
+            this.drawBaseLine(painter);
+        }
+    } // Function onDraw()
+} // Class SPolylineItem

+ 2 - 1
docs/guides/index.js

@@ -79,7 +79,8 @@ const content = [
                 title: "编辑器Item示例",
                 children: [
                     ["/guides/edit/items/editLine", "编辑线"],
-                    ["/guides/edit/items/editPolygonItem", "编辑多边形"],
+                    ["/guides/edit/items/editPolygon", "编辑多边形"],
+                    ["/guides/edit/items/editPolyline", "编辑折线"],
                 ]
             },
             ["/guides/edit/undo/undo", "Undo示例"],