SPolylineItem.ts 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. import { SColor, SLine, SPainter, SPoint } from "@saga-web/draw/lib";
  2. import { SMouseEvent } from "@saga-web/base";
  3. import { SItemStatus } from "..";
  4. import { SMathUtil } from "../utils/SMathUtil";
  5. import { SGraphItem } from "@saga-web/graph/lib";
  6. /**
  7. * 直线item
  8. *
  9. * */
  10. export class SPolylineItem extends SGraphItem {
  11. /** 折点信息 */
  12. pointList: SPoint[] = [];
  13. /** 是否绘制完成 */
  14. _status: SItemStatus = SItemStatus.Create;
  15. get status(): SItemStatus {
  16. return this._status;
  17. }
  18. set status(v: SItemStatus) {
  19. this._status = v;
  20. this.update();
  21. }
  22. /** 鼠标移动时的点 */
  23. lastPoint: SPoint | null = null;
  24. /** 线条颜色 */
  25. _strokeColor: string = "#000000";
  26. get strokeColor(): string {
  27. return this._strokeColor;
  28. }
  29. set strokeColor(v: string) {
  30. this._strokeColor = v;
  31. this.update();
  32. }
  33. /** 填充色 */
  34. _fillColor: string = "#2196f3";
  35. get fillColor(): string {
  36. return this._fillColor;
  37. }
  38. set fillColor(v: string) {
  39. this._fillColor = v;
  40. this.update();
  41. }
  42. /** 线条宽度 */
  43. _lineWidth: number = 1;
  44. get lineWidth(): number {
  45. return this._lineWidth;
  46. }
  47. set lineWidth(v: number) {
  48. this._lineWidth = v;
  49. this.update();
  50. }
  51. /** 全局灵敏度 */
  52. dis: number = 10;
  53. /** 灵敏度转换为场景长度 */
  54. sceneDis: number = 10;
  55. /** 当前点索引 */
  56. curIndex: number = -1;
  57. /**
  58. * 构造函数
  59. *
  60. * @param parent 父级
  61. * @param list 坐标集合
  62. * */
  63. constructor(parent: null | SGraphItem, list: SPoint[]);
  64. /**
  65. * 构造函数
  66. *
  67. * @param parent 父级
  68. * @param list 第一个坐标
  69. * */
  70. constructor(parent: null | SGraphItem, list: SPoint);
  71. /**
  72. * 构造函数
  73. *
  74. * @param parent 父级
  75. * @param list 第一个坐标|坐标集合
  76. * */
  77. constructor(parent: null | SGraphItem, list: SPoint | SPoint[]) {
  78. super(parent);
  79. if (list instanceof SPoint) {
  80. this.pointList.push(list);
  81. } else {
  82. this.pointList = list;
  83. }
  84. } // Constructor
  85. /**
  86. * 添加点至数组中
  87. *
  88. * @param p 添加的点
  89. * @param index 添加到的索引
  90. * */
  91. private addPoint(p: SPoint, index?: number): void {
  92. if (index && this.canHandle(index)) {
  93. this.pointList.splice(index, 0, p);
  94. } else {
  95. this.pointList.push(p);
  96. }
  97. this.update();
  98. } // Function addPoint()
  99. /**
  100. * 是否可以添加点到数组中
  101. *
  102. * @param index 要添加到的索引
  103. * @return boolean 是否可添加
  104. * */
  105. private canHandle(index: number): boolean {
  106. return index >= 0 && index <= this.pointList.length;
  107. } // Function canHandle()
  108. /**
  109. * 添加点至数组中
  110. *
  111. * @param index 添加到的索引
  112. * */
  113. private delPoint(index: number): void {
  114. if (this.canHandle(index) && this.pointList.length > 2) {
  115. this.pointList.splice(index, 0);
  116. this.update();
  117. }
  118. } // Function delPoint
  119. /**
  120. * 鼠标按下事件
  121. *
  122. * @param event 鼠标事件
  123. * @return boolean 是否处理事件
  124. * */
  125. onMouseDown(event: SMouseEvent): boolean {
  126. this.curIndex = -1;
  127. if (event.buttons == 1) {
  128. if (this.status == SItemStatus.Create) {
  129. this.addPoint(new SPoint(event.x, event.y));
  130. return true;
  131. } else if (this.status == SItemStatus.Edit) {
  132. // 查询鼠标最近的索引
  133. this.findNearestPoint(new SPoint(event.x, event.y));
  134. // 增加点
  135. // 删除点
  136. if (event.altKey && this.canHandle(this.curIndex)) {
  137. this.pointList.splice(this.curIndex, 1);
  138. this.curIndex = -1;
  139. }
  140. this.update();
  141. return true;
  142. } else {
  143. return super.onMouseDown(event);
  144. }
  145. }
  146. return super.onMouseDown(event);
  147. } // Function onMouseDown()
  148. /**
  149. * 鼠标移动事件
  150. *
  151. * @param event 鼠标事件
  152. * @return boolean 是否处理事件
  153. * */
  154. onMouseMove(event: SMouseEvent): boolean {
  155. if (this.status == SItemStatus.Create) {
  156. if (this.lastPoint) {
  157. this.lastPoint.x = event.x;
  158. this.lastPoint.y = event.y;
  159. } else {
  160. this.lastPoint = new SPoint(event.x, event.y);
  161. }
  162. this.update();
  163. return true;
  164. } else if (this.status == SItemStatus.Edit) {
  165. if (this.canHandle(this.curIndex)) {
  166. this.pointList[this.curIndex].x = event.x;
  167. this.pointList[this.curIndex].y = event.y;
  168. }
  169. this.update();
  170. return true;
  171. } else {
  172. return super.onMouseMove(event);
  173. }
  174. } // Function onMouseMove()
  175. /**
  176. * 鼠标移动事件
  177. *
  178. * @param event 鼠标事件
  179. * @return boolean 是否处理事件
  180. * */
  181. onMouseUp(event: SMouseEvent): boolean {
  182. this.curIndex = -1;
  183. return true;
  184. } // Function onMouseMove()
  185. /**
  186. * 鼠标双击事件
  187. *
  188. * @param event 事件参数
  189. * @return boolean
  190. */
  191. onDoubleClick(event: SMouseEvent): boolean {
  192. if (this.status == SItemStatus.Normal) {
  193. this.status = SItemStatus.Edit;
  194. } else if (this.status == SItemStatus.Edit) {
  195. this.status = SItemStatus.Normal;
  196. } else if (this.status == SItemStatus.Create) {
  197. this.status = SItemStatus.Edit;
  198. }
  199. this.$emit("onDoubleClick", event);
  200. return true;
  201. } // Function onDoubleClick()
  202. /***
  203. * 键盘按键弹起事件
  204. *
  205. * @param event 事件参数
  206. */
  207. onKeyUp(event: KeyboardEvent): void {
  208. if (event.keyCode == 13) {
  209. this.status = SItemStatus.Edit;
  210. }
  211. } // Function onKeyUp()
  212. /**
  213. * 获取点击点与点集中距离最近点
  214. *
  215. * @param p 鼠标点击点
  216. * */
  217. findNearestPoint(p: SPoint): void {
  218. let len = this.sceneDis;
  219. for (let i = 0; i < this.pointList.length; i++) {
  220. let dis = SMathUtil.pointDistance(
  221. p.x,
  222. p.y,
  223. this.pointList[i].x,
  224. this.pointList[i].y
  225. );
  226. if (dis < len) {
  227. len = dis;
  228. this.curIndex = i;
  229. }
  230. }
  231. } // Function findNearestPoint()
  232. /**
  233. * 计算增加点的位置
  234. *
  235. * @param p 鼠标点击点
  236. * */
  237. findAddPos(p: SPoint): void {
  238. let len = {
  239. MinDis: this.sceneDis
  240. },
  241. index = 0;
  242. if (this.pointList.length > 2) {
  243. for (let i = 0; i < this.pointList.length - 1; i++) {
  244. let dis = SMathUtil.pointToLine(
  245. new SPoint(p.x, p.y),
  246. new SLine(this.pointList[i], this.pointList[i + 1])
  247. );
  248. if (dis.MinDis < len.MinDis) {
  249. len = dis;
  250. index = i;
  251. }
  252. }
  253. // @ts-ignore
  254. if (len.Point) {
  255. // @ts-ignore
  256. this.addPoint(new SPoint(len.Point.X, len.Point.Y), index);
  257. }
  258. }
  259. } // Function findAddPos()
  260. /**
  261. * 判断点是否在区域内
  262. *
  263. * @param x
  264. * @param y
  265. * @return true-是
  266. */
  267. contains(x: number, y: number): boolean {
  268. let p = new SPoint(x, y);
  269. for (let i = 1; i < this.pointList.length; i++) {
  270. let PTL = SMathUtil.pointToLine(
  271. p,
  272. new SLine(
  273. this.pointList[i - 1].x,
  274. this.pointList[i - 1].y,
  275. this.pointList[i].x,
  276. this.pointList[i].y
  277. )
  278. );
  279. if (PTL.MinDis < this.sceneDis) {
  280. return true;
  281. }
  282. }
  283. return false;
  284. } // Function contains()
  285. /**
  286. * Item绘制操作
  287. *
  288. * @param painter painter对象
  289. */
  290. onDraw(painter: SPainter): void {
  291. // 缓存场景长度
  292. this.sceneDis = painter.toPx(this.dis);
  293. // 绘制基本图形
  294. painter.pen.lineWidth = painter.toPx(this.lineWidth);
  295. painter.pen.color = new SColor(this.strokeColor);
  296. painter.drawPolyline(this.pointList);
  297. // 创建状态
  298. if (this.status == SItemStatus.Create && this.lastPoint) {
  299. painter.drawLine(
  300. this.pointList[this.pointList.length - 1],
  301. this.lastPoint
  302. );
  303. } else if (this.status == SItemStatus.Edit) {
  304. // 编辑状态
  305. this.pointList.forEach((t, i): void => {
  306. painter.brush.color = SColor.White;
  307. if (i == this.curIndex) {
  308. painter.brush.color = new SColor(this.fillColor);
  309. }
  310. painter.drawCircle(t.x, t.y, painter.toPx(5));
  311. });
  312. }
  313. } // Function onDraw()
  314. } // Class SPolylineItem