SIconTextItem.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /*
  2. * *********************************************************************************************************************
  3. *
  4. * !!
  5. * .F88X
  6. * X8888Y
  7. * .}888888N;
  8. * i888888N; .:! .I$WI:
  9. * R888888I .'N88~ i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
  10. * .R888888I .;N8888~ .X8' "8I.!,/8" !%NY8`"8I8~~8>,88I
  11. * +888888N; .8888888Y "&&8Y.}8,
  12. * ./888888N; .R888888Y .'}~ .>}'.`+> i}! "i' +/' .'i~ !11,.:">, .~]! .i}i
  13. * ~888888%: .I888888l .]88~`1/iY88Ii+1'.R$8$8]"888888888> Y8$ W8E X8E W8888'188Il}Y88$*
  14. * 18888888 E8888881 .]W%8$`R8X'&8%++N8i,8N%N8+l8%` .}8N:.R$RE%N88N%N$K$R 188,FE$8%~Y88I
  15. * .E888888I .i8888888' .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
  16. * 8888888I .,N888888~ ~88i"8W,!N8*.I88.}888%F,i$88"F88" 888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
  17. * i888888N' I888Y ]88;/EX*IFKFK88X K8R .l8W 88Y ~88}'88E&%8W.X8N``]88!.$8K .:W8I
  18. * .i888888N; I8Y .&8$ .X88! i881.:%888>I88 ;88] +88+.';;;;:.Y88X 18N.,88l .+88/
  19. * .:R888888I
  20. * .&888888I Copyright (c) 2009-2021. 博锐尚格科技股份有限公司
  21. * ~8888'
  22. * .!88~ All rights reserved.
  23. *
  24. * *********************************************************************************************************************
  25. */
  26. import {
  27. SObjectItem,
  28. SImageItem,
  29. STextItem,
  30. SAnchorItem,
  31. SGraphItem
  32. } from "@persagy-web/graph";
  33. import { SItemStatus, ItemOrder } from "../../index";
  34. import { SMouseEvent } from "@persagy-web/base";
  35. import {
  36. SSize,
  37. SRect,
  38. SPainter,
  39. SColor,
  40. SFont,
  41. SPoint
  42. } from "@persagy-web/draw";
  43. import { Anchor } from "../../types/topology/Anchor";
  44. /**
  45. * 图例 item
  46. *
  47. * @author 郝建龙 <haojianlong@sagacloud.cn>
  48. */
  49. export class SIconTextItem extends SObjectItem {
  50. /** item 状态 */
  51. _status: SItemStatus = SItemStatus.Normal;
  52. get status(): SItemStatus {
  53. return this._status;
  54. }
  55. set status(v: SItemStatus) {
  56. this._status = v;
  57. // 标准状态时
  58. if (v == SItemStatus.Normal) {
  59. this.moveable = true;
  60. this.textItemList.forEach((t): void => {
  61. t.moveable = false;
  62. });
  63. this.img.moveable = false;
  64. } else if (v == SItemStatus.Edit) {
  65. // 编辑状态时
  66. this.moveable = false;
  67. this.textItemList.forEach((t): void => {
  68. t.moveable = true;
  69. });
  70. this.img.moveable = true;
  71. } else if (v == SItemStatus.Create) {
  72. // 创建状态时
  73. this.moveable = true;
  74. this.textItemList.forEach((t): void => {
  75. t.moveable = false;
  76. });
  77. this.img.moveable = false;
  78. }
  79. this.update();
  80. }
  81. /** 是否显示文字 */
  82. _showText: boolean = true;
  83. get showText(): boolean {
  84. return this._showText;
  85. }
  86. set showText(v: boolean) {
  87. // 当文字是显示状态时
  88. if (v === this._showText) {
  89. return;
  90. }
  91. this._showText = v;
  92. // 是否显示文字
  93. if (v) {
  94. this.textItemList.forEach((t): void => {
  95. t.show();
  96. });
  97. } else {
  98. this.textItemList.forEach((t): void => {
  99. t.hide();
  100. });
  101. }
  102. }
  103. /** 是否被选中 */
  104. get selected(): boolean {
  105. return this._selected && this.selectable && this.enabled;
  106. }
  107. set selected(value: boolean) {
  108. // 如果选择状态未变更
  109. if (this.selected == value) {
  110. return;
  111. }
  112. this._selected = value;
  113. // 选中时
  114. if (value) {
  115. this.img.scale = 1.25;
  116. this.zOrder = ItemOrder.highLightOrder;
  117. } else {
  118. this.img.scale = 1;
  119. this.zOrder = ItemOrder.markOrder;
  120. }
  121. this.update();
  122. }
  123. /** 是否激活 */
  124. _isActive: boolean = false;
  125. get isActive(): boolean {
  126. return this._isActive;
  127. }
  128. set isActive(v: boolean) {
  129. this._isActive = v;
  130. // 激活状态
  131. if (v) {
  132. this.cursor = "pointer";
  133. } else {
  134. this.cursor = "auto";
  135. }
  136. this.update();
  137. }
  138. /** 激活显示颜色 */
  139. _activeColor: SColor = new SColor("#00000033");
  140. get activeColor(): SColor {
  141. return this._activeColor;
  142. }
  143. set activeColor(v: SColor) {
  144. this._activeColor = v;
  145. this.update();
  146. }
  147. /** X 轴坐标 */
  148. get x(): number {
  149. return this.pos.x;
  150. }
  151. set x(v: number) {
  152. this.pos.x = v;
  153. this.$emit("changePos");
  154. this.update();
  155. }
  156. /** Y 轴坐标 */
  157. get y(): number {
  158. return this.pos.y;
  159. }
  160. set y(v: number) {
  161. this.pos.y = v;
  162. this.$emit("changePos");
  163. this.update();
  164. }
  165. /** icon宽 */
  166. get sWidth(): number {
  167. return this.img.width;
  168. }
  169. set sWidth(v: number) {
  170. this.img.width = v;
  171. this.img.origin = new SPoint(
  172. this.img.width * 0.5,
  173. this.img.height * 0.5
  174. );
  175. this.changeAnchorPoint();
  176. this.update();
  177. }
  178. /** icon高 */
  179. get sHeight(): number {
  180. return this.img.height;
  181. }
  182. set sHeight(v: number) {
  183. this.img.height = v;
  184. this.img.origin = new SPoint(
  185. this.img.width * 0.5,
  186. this.img.height * 0.5
  187. );
  188. this.changeAnchorPoint();
  189. this.update();
  190. }
  191. /** 是否显示锚点 */
  192. private _showAnchor: boolean = false;
  193. get showAnchor(): boolean {
  194. return this._showAnchor;
  195. }
  196. set showAnchor(v: boolean) {
  197. this._showAnchor = v;
  198. this.anchorList.forEach((t): void => {
  199. t.visible = v;
  200. });
  201. }
  202. /** 文本颜色 */
  203. get color(): SColor {
  204. if (this.textItemList.length) {
  205. return this.textItemList[0].color;
  206. } else {
  207. return new SColor();
  208. }
  209. }
  210. set color(v: SColor) {
  211. this.textItemList.forEach((item): void => {
  212. item.color = v;
  213. });
  214. this.update();
  215. }
  216. /** 文本字体 */
  217. get font(): SFont {
  218. if (this.textItemList.length) {
  219. return this.textItemList[0].font;
  220. } else {
  221. return new SFont();
  222. }
  223. }
  224. set font(v: SFont) {
  225. this.textItemList.forEach((item): void => {
  226. item.font = v;
  227. });
  228. this.update();
  229. }
  230. /** img Item */
  231. img: SImageItem = new SImageItem(this);
  232. /** text Item */
  233. textItemList: STextItem[] = [];
  234. /**
  235. * 构造体
  236. *
  237. * @param parent 父类
  238. * @param data 锚点数据
  239. */
  240. constructor(parent: SGraphItem | null, data?: Anchor[]) {
  241. super(parent);
  242. this.img.width = 32;
  243. this.img.height = 32;
  244. this.img.origin = new SPoint(
  245. this.img.width * 0.5,
  246. this.img.height * 0.5
  247. );
  248. this.img.connect("onMove", this, this.changeAnchorPoint.bind(this));
  249. let anchorPoint;
  250. // 锚点数据存在时
  251. if (data && data.length) {
  252. anchorPoint = data.map((t): any => {
  253. return {
  254. x: t.pos.x,
  255. y: t.pos.y,
  256. id: t.anchorId
  257. };
  258. });
  259. } else {
  260. anchorPoint = [
  261. { x: this.img.x, y: this.img.y, id: "" },
  262. { x: this.img.x, y: this.img.y, id: "" },
  263. { x: this.img.x, y: this.img.y, id: "" },
  264. { x: this.img.x, y: this.img.y, id: "" }
  265. // { x: this.img.x, y: this.img.y + this.img.height / 2, id: "" },
  266. // { x: this.img.x, y: this.img.y - this.img.height / 2, id: "" },
  267. // { x: this.img.x - this.img.width / 2, y: this.img.y, id: "" },
  268. // { x: this.img.x + this.img.width / 2, y: this.img.y, id: "" }
  269. ];
  270. }
  271. this.anchorList = anchorPoint.map(
  272. (t): SAnchorItem => {
  273. let item = new SAnchorItem(this);
  274. if (t.id) {
  275. item.id = t.id;
  276. }
  277. item.moveTo(t.x, t.y);
  278. return item;
  279. }
  280. );
  281. this.showAnchor = false;
  282. // this.textItem.text = "";
  283. // this.textItem.font.size = 12;
  284. // // 偏移二分之一文本高度
  285. // this.textItem.moveTo(
  286. // this.img.width * 0.5,
  287. // -(this.font.size * 1.25 * 0.5)
  288. // );
  289. this.moveable = true;
  290. this.selectable = true;
  291. }
  292. /**
  293. * 计算并移动锚点的位置
  294. */
  295. private changeAnchorPoint(): void {
  296. // 判断是否有锚点
  297. if (this.anchorList.length) {
  298. let anchorPoint = [
  299. { x: this.img.x, y: this.img.y },
  300. { x: this.img.x, y: this.img.y },
  301. { x: this.img.x, y: this.img.y },
  302. { x: this.img.x, y: this.img.y }
  303. // { x: this.img.x, y: this.img.y + this.img.height / 2 },
  304. // { x: this.img.x, y: this.img.y - this.img.height / 2 },
  305. // { x: this.img.x - this.img.width / 2, y: this.img.y },
  306. // { x: this.img.x + this.img.width / 2, y: this.img.y }
  307. ];
  308. this.anchorList.forEach((item, index): void => {
  309. item.moveTo(anchorPoint[index].x, anchorPoint[index].y);
  310. });
  311. }
  312. }
  313. /**
  314. * 添加文本
  315. *
  316. * @param item 文本图例
  317. */
  318. addTextItem(item: STextItem): void {
  319. this.textItemList.push(item);
  320. }
  321. /**
  322. * 删除文本
  323. *
  324. * @param index 索引
  325. */
  326. removeTextItem(index: number): void {
  327. let [deleteItem] = this.textItemList.splice(index, 1);
  328. if (this.scene) {
  329. this.scene.removeItem(deleteItem);
  330. }
  331. }
  332. /**
  333. * 宽高发发生变化
  334. *
  335. * @param oldSize 改之前的大小
  336. * @param newSize 改之后大小
  337. */
  338. onResize(oldSize: SSize, newSize: SSize): void {
  339. console.log(arguments);
  340. }
  341. /**
  342. * Item 对象边界区域
  343. *
  344. * @return 边界矩阵
  345. */
  346. boundingRect(): SRect {
  347. let rect = this.img
  348. .boundingRect()
  349. .adjusted(this.img.pos.x, this.img.pos.y, 0, 0);
  350. // 显示文字时
  351. if (this.showText) {
  352. this.textItemList.forEach((t): void => {
  353. rect = rect.unioned(
  354. t.boundingRect().adjusted(t.pos.x, t.pos.y, 0, 0)
  355. );
  356. });
  357. }
  358. return rect.adjusted(-5, -5, 10, 10);
  359. }
  360. /**
  361. * Item 绘制操作
  362. *
  363. * @param painter 绘制对象
  364. */
  365. onDraw(painter: SPainter): void {
  366. const rect = this.boundingRect();
  367. const lw = painter.toPx(1);
  368. // 编辑态和选中态出现绘制区域
  369. if (this.status == SItemStatus.Edit || this.selected) {
  370. // doto 如果子元素被选中
  371. painter.pen.lineWidth = lw;
  372. painter.pen.lineDash = [3 * lw, 7 * lw];
  373. painter.pen.color = SColor.Black;
  374. painter.brush.color = SColor.Transparent;
  375. painter.drawRect(rect);
  376. }
  377. // 编辑态出现四个角的圆点
  378. if (this.status == SItemStatus.Edit) {
  379. painter.pen.lineDash = [];
  380. painter.brush.color = SColor.White;
  381. painter.drawCircle(rect.x, rect.y, 5 * lw);
  382. painter.drawCircle(rect.right, rect.bottom, 5 * lw);
  383. painter.drawCircle(rect.x, rect.bottom, 5 * lw);
  384. painter.drawCircle(rect.right, rect.y, 5 * lw);
  385. }
  386. // 处于激活状态时
  387. if (this.isActive) {
  388. painter.pen.color = SColor.Transparent;
  389. painter.brush.color = this.activeColor;
  390. // 是否选中
  391. if (this.selected) {
  392. painter.shadow.shadowBlur = 10;
  393. painter.shadow.shadowColor = this.activeColor;
  394. painter.shadow.shadowOffsetX = 5;
  395. painter.shadow.shadowOffsetY = 5;
  396. painter.drawCircle(
  397. this.img.x,
  398. this.img.y,
  399. (this.sWidth / 2.0 + 3) * 1.25
  400. );
  401. } else {
  402. painter.drawCircle(
  403. this.img.x,
  404. this.img.y,
  405. this.sWidth / 2.0 + 3
  406. );
  407. }
  408. } else {
  409. // 是否选中
  410. if (this.selected) {
  411. painter.pen.color = SColor.Transparent;
  412. painter.brush.color = SColor.Transparent;
  413. painter.shadow.shadowBlur = 10;
  414. painter.shadow.shadowColor = new SColor(`#00000033`);
  415. painter.shadow.shadowOffsetX = 5;
  416. painter.shadow.shadowOffsetY = 5;
  417. painter.drawCircle(this.img.x, this.img.y, this.sWidth / 2.0);
  418. }
  419. }
  420. }
  421. }