SPolygonItem.ts 23 KB

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