EditPolygonItem.ts 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. import {
  2. SGraphItem,
  3. SGraphPointListDelete,
  4. SGraphPointListInsert,
  5. SGraphPointListUpdate,
  6. SLineStyle
  7. } from "@persagy-web/graph/lib";
  8. import { SKeyCode, SMouseEvent, SUndoStack } from "@persagy-web/base/";
  9. import {
  10. SColor,
  11. SLine,
  12. SLineCapStyle,
  13. SPainter,
  14. SPoint,
  15. SPolygonUtil,
  16. SRect
  17. } from "@persagy-web/draw";
  18. import { SItemStatus } from "@persagy-web/big";
  19. import { SMathUtil } from "@persagy-web/big/lib/utils/SMathUtil";
  20. /**
  21. * 编辑多边形
  22. *
  23. * @author 韩耀龙
  24. */
  25. export class EditPolygonItem extends SGraphItem {
  26. /** X坐标最小值 */
  27. private minX = Number.MAX_SAFE_INTEGER;
  28. /** X坐标最大值 */
  29. private maxX = Number.MIN_SAFE_INTEGER;
  30. /** Y坐标最小值 */
  31. private minY = Number.MAX_SAFE_INTEGER;
  32. /** Y坐标最大值 */
  33. private maxY = Number.MIN_SAFE_INTEGER;
  34. /** 轮廓线坐标 */
  35. private pointList: SPoint[] = [];
  36. // 获取当前状态
  37. get getPointList(): SPoint[] {
  38. return this.pointList;
  39. }
  40. // 编辑当前状态
  41. set setPointList(arr: SPoint[]) {
  42. this.pointList = arr;
  43. this.update();
  44. }
  45. /** 是否垂直水平绘制 */
  46. private _verAndLeve: Boolean = false;
  47. get verAndLeve(): Boolean {
  48. return this._verAndLeve;
  49. }
  50. set verAndLeve(bool: Boolean) {
  51. this._verAndLeve = bool;
  52. this.update();
  53. }
  54. // 当前状态
  55. protected _status: number = SItemStatus.Normal;
  56. // 获取当前状态
  57. get status(): SItemStatus {
  58. return this._status;
  59. }
  60. // 编辑当前状态
  61. set status(value: SItemStatus) {
  62. this._status = value;
  63. this.undoStack.clear();
  64. this.update();
  65. }
  66. /** 边框颜色 */
  67. _strokeColor: SColor = new SColor("#0091FF");
  68. /** 画笔颜色 */
  69. get strokeColor(): SColor {
  70. return this._strokeColor;
  71. }
  72. set strokeColor(v: SColor) {
  73. this._strokeColor = v;
  74. this.update();
  75. }
  76. /** 填充颜色 */
  77. _fillColor: SColor = new SColor("#1EE887");
  78. get fillColor(): SColor {
  79. return this._fillColor;
  80. }
  81. set fillColor(v: SColor) {
  82. this._fillColor = v;
  83. this.update();
  84. }
  85. /** 边框样式 */
  86. _lineStyle: SLineStyle = SLineStyle.Solid;
  87. get lineStyle(): SLineStyle {
  88. return this._lineStyle;
  89. }
  90. set lineStyle(v: SLineStyle) {
  91. this._lineStyle = v;
  92. this.update();
  93. }
  94. /** 边框的宽 只可输入像素宽*/
  95. _lineWidth: number = 4;
  96. get lineWidth(): number {
  97. return this._lineWidth;
  98. }
  99. set lineWidth(v: number) {
  100. this._lineWidth = v;
  101. this.update();
  102. }
  103. /** 是否闭合 */
  104. closeFlag: boolean = false;
  105. /** 鼠标移动点 */
  106. private lastPoint: SPoint | null = null;
  107. /** 当前鼠标获取顶点对应索引 */
  108. private curIndex: number = -1;
  109. /** 当前鼠标获取顶点对应坐标 */
  110. private curPoint: null | SPoint = null;
  111. /** 灵敏像素 */
  112. private len: number = 10;
  113. /** 场景像素 内部将灵敏像素换算为场景实际距离 */
  114. private scenceLen: number = 15;
  115. /** 场景像素 */
  116. private isAlt: boolean = false;
  117. /** undoredo堆栈 */
  118. protected undoStack: SUndoStack = new SUndoStack();
  119. /**
  120. * 构造函数
  121. *
  122. * @param parent 指向父对象
  123. */
  124. constructor(parent: SGraphItem | null) {
  125. super(parent);
  126. }
  127. //////////////////
  128. // 以下为对pointList 数组的操作方法
  129. /**
  130. * 储存新的多边形顶点
  131. *
  132. * @param x 点位得x坐标
  133. * @param y 点位得y坐标
  134. * @param i 储存所在索引
  135. * @return SPoint。添加的顶点
  136. */
  137. insertPoint(x: number, y: number, i: number | null = null): SPoint {
  138. const point = new SPoint(x, y);
  139. if (i == null) {
  140. this.pointList.push(point);
  141. } else {
  142. this.pointList.splice(i, 0, point);
  143. }
  144. this.update();
  145. return point;
  146. }
  147. /**
  148. * 删除点位
  149. *
  150. * @param i 删除点所在的索引
  151. * @return SPoint|null。索引不在数组范围则返回null
  152. */
  153. deletePoint(i: number | null = null): SPoint | null {
  154. let point = null;
  155. if (i != null) {
  156. if (i >= this.pointList.length || i < 0) {
  157. point = null;
  158. } else {
  159. point = new SPoint(this.pointList[i].x, this.pointList[i].y);
  160. this.pointList.splice(i, 1);
  161. }
  162. } else {
  163. if (this.pointList.length) {
  164. point = this.pointList[this.pointList.length - 1];
  165. this.pointList.pop();
  166. } else {
  167. point = null;
  168. }
  169. }
  170. this.curIndex = -1;
  171. this.curPoint = null;
  172. this.update();
  173. return point;
  174. }
  175. /**
  176. * 多边形顶点的移动位置
  177. *
  178. * @param x 点位得x坐标
  179. * @param y 点位得y坐标
  180. * @param i 点位得i坐标
  181. * @return 移动对应得点。如果索引无法找到移动顶点,则返回null
  182. */
  183. movePoint(x: number, y: number, i: number): SPoint | null {
  184. let point = null;
  185. if (i >= this.pointList.length || i < 0) {
  186. return null;
  187. }
  188. if (this.pointList.length) {
  189. this.pointList[i].x = x;
  190. this.pointList[i].y = y;
  191. }
  192. point = this.pointList[i];
  193. return point;
  194. }
  195. /**
  196. * 打印出多边形数组
  197. *
  198. * @return 顶点数组
  199. */
  200. PrintPointList(): SPoint[] {
  201. return this.pointList;
  202. }
  203. ////////////
  204. // 以下为三种状态下的绘制多边形方法
  205. /**
  206. * 展示状态 --绘制多边形数组
  207. *
  208. * @param painter 绘制类
  209. * @param pointList 绘制多边形数组
  210. */
  211. protected drawShowPolygon(painter: SPainter, pointList: SPoint[]): void {
  212. painter.save();
  213. painter.pen.lineCapStyle = SLineCapStyle.Square;
  214. painter.pen.color = this.strokeColor;
  215. painter.brush.color = this.fillColor;
  216. painter.pen.lineWidth = painter.toPx(this.lineWidth);
  217. if (this.lineStyle == SLineStyle.Dashed) {
  218. painter.pen.lineDash = [
  219. painter.toPx(this.lineWidth * 3),
  220. painter.toPx(this.lineWidth * 7)
  221. ];
  222. } else if (this.lineStyle == SLineStyle.Dotted) {
  223. painter.pen.lineDash = [
  224. painter.toPx(this.lineWidth),
  225. painter.toPx(this.lineWidth)
  226. ];
  227. }
  228. if (this.selected) {
  229. painter.shadow.shadowBlur = 10;
  230. painter.shadow.shadowColor = new SColor(`#00000033`);
  231. painter.shadow.shadowOffsetX = 5;
  232. painter.shadow.shadowOffsetY = 5;
  233. } else {
  234. painter.shadow.shadowColor = SColor.Transparent;
  235. }
  236. painter.drawPolygon([...pointList]);
  237. painter.restore();
  238. }
  239. /**
  240. * 创建状态 --绘制多边形数组
  241. *
  242. * @param painter 绘制类
  243. * @param pointList 绘制多边形数组
  244. */
  245. protected drawCreatePolygon(painter: SPainter, pointList: SPoint[]): void {
  246. painter.pen.lineCapStyle = SLineCapStyle.Square;
  247. painter.pen.color = this.strokeColor;
  248. painter.pen.lineWidth = painter.toPx(this.lineWidth);
  249. if (this.lastPoint && pointList.length) {
  250. painter.drawLine(
  251. pointList[pointList.length - 1].x,
  252. pointList[pointList.length - 1].y,
  253. this.lastPoint.x,
  254. this.lastPoint.y
  255. );
  256. }
  257. painter.drawPolyline(pointList);
  258. painter.pen.color = SColor.Transparent;
  259. painter.brush.color = new SColor(this.fillColor.value);
  260. painter.pen.lineWidth = painter.toPx(this.lineWidth);
  261. if (this.lastPoint) {
  262. painter.drawPolygon([...pointList, this.lastPoint]);
  263. // 绘制顶点块
  264. painter.pen.color = SColor.Black;
  265. painter.brush.color = SColor.White;
  266. pointList.forEach(item => {
  267. painter.drawCircle(item.x, item.y, painter.toPx(this.len / 2));
  268. });
  269. // 如果最后一个点在第一个点的灵敏度范围内,第一个点填充变红
  270. if (this.pointList.length) {
  271. if (
  272. SMathUtil.pointDistance(
  273. this.lastPoint.x,
  274. this.lastPoint.y,
  275. this.pointList[0].x,
  276. this.pointList[0].y
  277. ) < this.scenceLen
  278. ) {
  279. // 绘制第一个点的顶点块
  280. painter.pen.color = SColor.Black;
  281. painter.brush.color = SColor.Red;
  282. painter.drawCircle(
  283. this.pointList[0].x,
  284. this.pointList[0].y,
  285. painter.toPx(this.len / 2)
  286. );
  287. }
  288. }
  289. } else {
  290. painter.drawPolygon(pointList);
  291. }
  292. }
  293. /**
  294. *
  295. * 编辑状态 --绘制多边形数组
  296. *
  297. * @param painter 绘制类
  298. * @param pointList 绘制多边形数组
  299. */
  300. protected drawEditPolygon(painter: SPainter, pointList: SPoint[]): void {
  301. // 展示多边形
  302. painter.pen.lineCapStyle = SLineCapStyle.Square;
  303. painter.pen.color = this.strokeColor;
  304. painter.pen.lineWidth = painter.toPx(this.lineWidth);
  305. painter.brush.color = new SColor(this.fillColor.value);
  306. painter.drawPolygon([...pointList]);
  307. // 绘制顶点块
  308. painter.pen.color = SColor.Black;
  309. painter.brush.color = SColor.White;
  310. pointList.forEach((item, index) => {
  311. painter.brush.color = SColor.White;
  312. if (index == this.curIndex) {
  313. painter.brush.color = new SColor("#2196f3");
  314. }
  315. painter.drawCircle(item.x, item.y, painter.toPx(this.len / 2));
  316. });
  317. }
  318. /**
  319. * 编辑状态操作多边形数组
  320. *
  321. * @param event 鼠标事件
  322. *
  323. *
  324. */
  325. protected editPolygonPoint(event: SMouseEvent): void {
  326. // 判断是否为删除状态 isAlt = true为删除状态
  327. if (this.isAlt) {
  328. // 1 判断是否点击在多边形顶点
  329. let lenIndex = -1; // 当前点击到的点位索引;
  330. let curenLen = this.scenceLen; // 当前的灵敏度
  331. this.pointList.forEach((item, index) => {
  332. let dis = SMathUtil.pointDistance(
  333. event.x,
  334. event.y,
  335. item.x,
  336. item.y
  337. );
  338. if (dis < curenLen) {
  339. curenLen = dis;
  340. lenIndex = index;
  341. }
  342. });
  343. // 若点击到,对该索引对应的点做删除
  344. if (lenIndex != -1) {
  345. if (this.pointList.length <= 3) {
  346. return;
  347. }
  348. const delePoint = new SPoint(
  349. this.pointList[lenIndex].x,
  350. this.pointList[lenIndex].y
  351. );
  352. this.deletePoint(lenIndex);
  353. // 记录顶点操作记录压入堆栈
  354. this.recordAction(SGraphPointListDelete, [
  355. this.pointList,
  356. delePoint,
  357. lenIndex
  358. ]);
  359. }
  360. } else {
  361. // 1 判断是否点击在多边形顶点
  362. this.curIndex = -1;
  363. this.curPoint = null;
  364. let lenIndex = -1; // 当前点击到的点位索引;
  365. let curenLen = this.scenceLen; // 当前的灵敏度
  366. this.pointList.forEach((item, index) => {
  367. let dis = SMathUtil.pointDistance(
  368. event.x,
  369. event.y,
  370. item.x,
  371. item.y
  372. );
  373. if (dis < curenLen) {
  374. curenLen = dis;
  375. lenIndex = index;
  376. }
  377. });
  378. this.curIndex = lenIndex;
  379. // 2判断是否点击在多边形得边上
  380. if (-1 == lenIndex) {
  381. let len = SMathUtil.pointToLine(
  382. new SPoint(event.x, event.y),
  383. new SLine(this.pointList[0], this.pointList[1])
  384. ),
  385. index = 0;
  386. if (this.pointList.length > 2) {
  387. for (let i = 1; i < this.pointList.length; i++) {
  388. let dis = SMathUtil.pointToLine(
  389. new SPoint(event.x, event.y),
  390. new SLine(this.pointList[i], this.pointList[i + 1])
  391. );
  392. if (i + 1 == this.pointList.length) {
  393. dis = SMathUtil.pointToLine(
  394. new SPoint(event.x, event.y),
  395. new SLine(this.pointList[i], this.pointList[0])
  396. );
  397. }
  398. if (dis.MinDis < len.MinDis) {
  399. len = dis;
  400. index = i;
  401. }
  402. }
  403. }
  404. // 判断是否有点
  405. if (len.Point) {
  406. // 点在了多边形的边上
  407. if (len.MinDis <= this.scenceLen) {
  408. this.pointList.splice(index + 1, 0, len.Point);
  409. // 记录新增顶点操作记录压入堆栈
  410. this.recordAction(SGraphPointListInsert, [
  411. this.pointList,
  412. len.Point,
  413. index + 1
  414. ]);
  415. } else {
  416. //没点在多边形边上也没点在多边形顶点上
  417. super.onMouseDown(event);
  418. }
  419. }
  420. } else {
  421. // 当捕捉到顶点后 ,记录当前点的xy坐标,用于undo、redo操作
  422. this.curPoint = new SPoint(
  423. this.pointList[this.curIndex].x,
  424. this.pointList[this.curIndex].y
  425. );
  426. }
  427. // 刷新视图
  428. this.update();
  429. }
  430. }
  431. /////////////////////
  432. // undo、redo相关操作
  433. /**
  434. * 记录相关动作并推入栈中
  435. * @param SGraphCommand 相关命令类
  436. * @param any 对应传入参数
  437. */
  438. protected recordAction(SGraphCommand: any, any: any[]): void {
  439. // 记录相关命令并推入堆栈中
  440. const sgraphcommand = new SGraphCommand(this.scene, this, ...any);
  441. this.undoStack.push(sgraphcommand);
  442. }
  443. /**
  444. * 执行取消操作执行
  445. */
  446. undo(): void {
  447. if (this.status == SItemStatus.Normal) {
  448. return;
  449. }
  450. this.undoStack.undo();
  451. }
  452. /**
  453. * 执行重做操作执行
  454. */
  455. redo(): void {
  456. if (this.status == SItemStatus.Normal) {
  457. return;
  458. }
  459. this.undoStack.redo();
  460. }
  461. ///////////////////////////////
  462. // 以下为鼠标事件
  463. /**
  464. * 鼠标双击事件
  465. *
  466. * @param event 事件参数
  467. * @return boolean
  468. */
  469. onDoubleClick(event: SMouseEvent): boolean {
  470. // 如果位show状态 双击改对象则需改为编辑状态
  471. if (SItemStatus.Normal == this.status) {
  472. this.status = SItemStatus.Edit;
  473. this.grabItem(this);
  474. } else if (SItemStatus.Edit == this.status) {
  475. this.status = SItemStatus.Normal;
  476. this.releaseItem();
  477. }
  478. this.update();
  479. return true;
  480. } // Function onDoubleClick()
  481. /**
  482. * 键盘事件
  483. *
  484. * @param event 事件参数
  485. * @return boolean
  486. */
  487. onKeyDown(event: KeyboardEvent): boolean {
  488. if (this.status == SItemStatus.Normal) {
  489. return false;
  490. } else if (this.status == SItemStatus.Create) {
  491. if (event.code == "Enter") {
  492. // 当顶点大于二个时才又条件执行闭合操作并清空堆栈
  493. if (this.pointList.length > 2) {
  494. this.status = SItemStatus.Normal;
  495. //3 传递完成事件状态
  496. this.$emit("finishCreated");
  497. //1 grabItem 置为null
  498. this.releaseItem();
  499. }
  500. }
  501. } else if (this.status == SItemStatus.Edit) {
  502. if (event.key == "Alt") {
  503. this.isAlt = true;
  504. }
  505. }
  506. this.update();
  507. return true;
  508. } // Function onKeyDown()
  509. /**
  510. * 键盘键抬起事件
  511. *
  512. * @param event 事件参数
  513. * @return boolean
  514. */
  515. onKeyUp(event: KeyboardEvent): void {
  516. if (this.status == SItemStatus.Edit) {
  517. if (event.key == "Alt") {
  518. this.isAlt = false;
  519. } else if (event.keyCode == SKeyCode.Delete) {
  520. // 当多边形的顶点大于三个允许删除点
  521. if (this.pointList.length > 3) {
  522. this.deletePoint(this.curIndex);
  523. }
  524. }
  525. }
  526. this.update();
  527. } // Function onKeyUp()
  528. /**
  529. * 鼠标按下事件
  530. *
  531. * @param event 事件参数
  532. * @return boolean
  533. */
  534. onMouseDown(event: SMouseEvent): boolean {
  535. if (event.shiftKey || this.verAndLeve) {
  536. event = this.compare(event);
  537. }
  538. // 如果状态为编辑状态则添加点
  539. if (this.status == SItemStatus.Create) {
  540. // 新增顶点
  541. let len = -1;
  542. if (this.pointList.length) {
  543. len = SMathUtil.pointDistance(
  544. event.x,
  545. event.y,
  546. this.pointList[0].x,
  547. this.pointList[0].y
  548. );
  549. }
  550. if (this.pointList.length > 2 && len > 0 && len < this.scenceLen) {
  551. this.status = SItemStatus.Normal;
  552. //3 传递完成事件状态
  553. this.$emit("finishCreated");
  554. //1 grabItem 置为null
  555. this.releaseItem();
  556. } else {
  557. this.insertPoint(event.x, event.y);
  558. // 记录新增顶点操作记录压入堆栈
  559. let pos = new SPoint(event.x, event.y);
  560. this.recordAction(SGraphPointListInsert, [this.pointList, pos]);
  561. }
  562. } else if (this.status == SItemStatus.Edit) {
  563. // 对多边形数组做编辑操作
  564. this.editPolygonPoint(event);
  565. } else {
  566. return super.onMouseDown(event);
  567. }
  568. return true;
  569. } // Function onMouseDown()
  570. /**
  571. * 鼠标移入事件
  572. *
  573. * @param event 事件参数
  574. * @return boolean
  575. */
  576. onMouseEnter(event: SMouseEvent): boolean {
  577. return true;
  578. } // Function onMouseEnter()
  579. /**
  580. * 鼠标移出事件
  581. *
  582. * @param event 事件参数
  583. * @return boolean
  584. */
  585. onMouseLeave(event: SMouseEvent): boolean {
  586. return true;
  587. } // Function onMouseLeave()
  588. /**
  589. * 鼠标移动事件
  590. *
  591. * @param event 事件参数
  592. * @return boolean
  593. */
  594. onMouseMove(event: SMouseEvent): boolean {
  595. if (event.shiftKey || this.verAndLeve) {
  596. event = this.compare(event);
  597. }
  598. if (this.status == SItemStatus.Create) {
  599. this.lastPoint = new SPoint();
  600. this.lastPoint.x = event.x;
  601. this.lastPoint.y = event.y;
  602. this.update();
  603. } else if (this.status == SItemStatus.Edit) {
  604. if (event.buttons == 1) {
  605. if (-1 != this.curIndex) {
  606. this.pointList[this.curIndex].x = event.x;
  607. this.pointList[this.curIndex].y = event.y;
  608. }
  609. }
  610. this.update();
  611. } else {
  612. return super.onMouseMove(event);
  613. }
  614. return true;
  615. } // Function onMouseMove()
  616. /**
  617. * shift垂直水平创建或编辑
  618. *
  619. * @param event 事件
  620. * */
  621. compare(event: SMouseEvent): SMouseEvent {
  622. if (this.pointList.length) {
  623. let last = new SPoint(event.x, event.y);
  624. if (this.status == SItemStatus.Create) {
  625. last = this.pointList[this.pointList.length - 1];
  626. } else if (this.status == SItemStatus.Edit) {
  627. if (this.curIndex > 1) {
  628. last = this.pointList[this.curIndex - 1];
  629. }
  630. }
  631. const dx = Math.abs(event.x - last.x);
  632. const dy = Math.abs(event.y - last.y);
  633. if (dy > dx) {
  634. event.x = last.x;
  635. } else {
  636. event.y = last.y;
  637. }
  638. }
  639. return event;
  640. } // Function compare()
  641. /**
  642. * 鼠标抬起事件
  643. *
  644. * @param event 事件参数
  645. * @return boolean
  646. */
  647. onMouseUp(event: SMouseEvent): boolean {
  648. if (this.status == SItemStatus.Edit) {
  649. if (-1 != this.curIndex) {
  650. const pos = new SPoint(
  651. this.pointList[this.curIndex].x,
  652. this.pointList[this.curIndex].y
  653. );
  654. this.recordAction(SGraphPointListUpdate, [
  655. this.pointList,
  656. this.curPoint,
  657. pos,
  658. this.curIndex
  659. ]);
  660. }
  661. } else if (this.status == SItemStatus.Normal) {
  662. this.moveToOrigin(this.x, this.y);
  663. return super.onMouseUp(event);
  664. }
  665. return true;
  666. } // Function onMouseUp()
  667. /**
  668. * 移动后处理所有坐标,并肩原点置为场景原点
  669. *
  670. * @param x x坐标
  671. * @param y y坐标
  672. * */
  673. moveToOrigin(x: number, y: number): void {
  674. super.moveToOrigin(x, y);
  675. this.pointList = this.pointList.map(t => {
  676. t.x = t.x + x;
  677. t.y = t.y + y;
  678. return t;
  679. });
  680. this.x = 0;
  681. this.y = 0;
  682. } // Function moveToOrigin()
  683. /**
  684. * 适配事件
  685. *
  686. * @param event 事件参数
  687. * @return boolean
  688. */
  689. onResize(event: SMouseEvent): boolean {
  690. return true;
  691. } // Function onResize()
  692. /**
  693. * 取消操作
  694. *
  695. */
  696. cancelOperate(): void {
  697. // 当状态为展示状态
  698. if (this.status == SItemStatus.Create) {
  699. // 闭合多边形
  700. this.parent = null;
  701. } else if (this.status == SItemStatus.Edit) {
  702. // 编辑状态
  703. this.status = SItemStatus.Normal;
  704. }
  705. this.update();
  706. } // Function cancelOperate()
  707. /**
  708. * Item对象边界区域
  709. *
  710. * @return SRect
  711. */
  712. boundingRect(): SRect {
  713. if (this.pointList.length) {
  714. this.minX = this.pointList[0].x;
  715. this.maxX = this.pointList[0].x;
  716. this.minY = this.pointList[0].y;
  717. this.maxY = this.pointList[0].y;
  718. this.pointList.forEach(it => {
  719. let x = it.x,
  720. y = it.y;
  721. if (x < this.minX) {
  722. this.minX = x;
  723. }
  724. if (y < this.minY) {
  725. this.minY = y;
  726. }
  727. if (x > this.maxX) {
  728. this.maxX = x;
  729. }
  730. if (y > this.maxY) {
  731. this.maxY = y;
  732. }
  733. });
  734. }
  735. return new SRect(
  736. this.minX,
  737. this.minY,
  738. this.maxX - this.minX,
  739. this.maxY - this.minY
  740. );
  741. } // Function boundingRect()
  742. /**
  743. * 判断点是否在区域内
  744. *
  745. * @param x
  746. * @param y
  747. */
  748. contains(x: number, y: number): boolean {
  749. let arr = this.pointList;
  750. if (arr.length < 3 || !SPolygonUtil.pointIn(x, y, arr)) {
  751. return false;
  752. }
  753. return true;
  754. } // Function contains()
  755. /**
  756. * Item绘制操作
  757. *
  758. * @param painter painter对象
  759. */
  760. onDraw(painter: SPainter): void {
  761. this.scenceLen = painter.toPx(this.len);
  762. // 当状态为展示状态
  763. if (this.status == SItemStatus.Normal) {
  764. // 闭合多边形
  765. this.drawShowPolygon(painter, this.pointList);
  766. } else if (this.status == SItemStatus.Create) {
  767. // 创建状态
  768. this.drawCreatePolygon(painter, this.pointList);
  769. } else {
  770. // 编辑状态
  771. this.drawEditPolygon(painter, this.pointList);
  772. }
  773. } // Function onDraw()
  774. }