SBaseIconTextEdit.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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-2020. 博锐尚格科技股份有限公司
  21. * ~8888'
  22. * .!88~ All rights reserved.
  23. *
  24. * *********************************************************************************************************************
  25. */
  26. import { SAnchorItem, SGraphItem } from "@persagy-web/graph";
  27. import { SItemStatus, ItemOrder } from "@persagy-web/big";
  28. import { SMouseEvent } from "@persagy-web/base";
  29. import {
  30. SSize,
  31. SRect,
  32. SPainter,
  33. SColor,
  34. SFont,
  35. SPoint
  36. } from "@persagy-web/draw";
  37. import { SGraphEdit, SBaseTextEdit, SBaseImageEdit } from "..";
  38. import { Marker } from "../type/Marker";
  39. /**
  40. * 图标
  41. *
  42. * @author 韩耀龙 <han_yao_long@163.com>
  43. */
  44. export class SBaseIconTextEdit extends SGraphEdit {
  45. /** item 数据*/
  46. _data: Marker | null = null;
  47. get data(): Marker | null {
  48. return this._data;
  49. } // Get data
  50. set data(v: Marker | null) {
  51. this._data = v;
  52. this.initData();
  53. this.update();
  54. } // Set data
  55. /** item 状态 */
  56. _status: SItemStatus = SItemStatus.Normal;
  57. get status(): SItemStatus {
  58. return this._status;
  59. }
  60. set status(v: SItemStatus) {
  61. this._status = v;
  62. if (v == SItemStatus.Normal) {
  63. this.moveable = true;
  64. this.textItemList.map(item => {
  65. item.moveable = false;
  66. });
  67. this.img.moveable = false;
  68. } else if (v == SItemStatus.Edit) {
  69. this.moveable = false;
  70. this.textItemList.map(item => {
  71. item.moveable = true;
  72. });
  73. this.img.moveable = true;
  74. } else if (v == SItemStatus.Create) {
  75. this.moveable = true;
  76. this.textItemList.map(item => {
  77. item.moveable = false;
  78. });
  79. this.img.moveable = false;
  80. }
  81. this.update();
  82. }
  83. /** 锚点 list */
  84. anchorList: SAnchorItem[] = [];
  85. /** 是否显示文字 */
  86. _showText: boolean = true;
  87. get showText(): boolean {
  88. return this._showText;
  89. }
  90. set showText(v: boolean) {
  91. if (v === this._showText) {
  92. return;
  93. }
  94. this._showText = v;
  95. if (v) {
  96. this.textItemList.map(item => {
  97. item.show();
  98. });
  99. } else {
  100. this.textItemList.map(item => {
  101. item.hide();
  102. });
  103. }
  104. }
  105. /** 是否被选中 */
  106. get selected(): boolean {
  107. return this._selected && this.selectable && this.enabled;
  108. }
  109. set selected(value: boolean) {
  110. // 如果选择状态未变更
  111. if (this.selected == value) {
  112. return;
  113. }
  114. this._selected = value;
  115. if (value) {
  116. this.img.scale = 1.25;
  117. this.zOrder = ItemOrder.highLightOrder;
  118. } else {
  119. this.img.scale = 1;
  120. this.zOrder = ItemOrder.markOrder;
  121. }
  122. this.update();
  123. }
  124. /** 是否激活 */
  125. _isActive: boolean = false;
  126. get isActive(): boolean {
  127. return this._isActive;
  128. }
  129. set isActive(v: boolean) {
  130. this._isActive = v;
  131. if (v) {
  132. this.cursor = "pointer";
  133. this.textItemList.map(item => {
  134. item.cursor = "pointer";
  135. });
  136. this.img.cursor = "pointer";
  137. } else {
  138. this.cursor = "auto";
  139. this.textItemList.map(item => {
  140. item.cursor = "auto";
  141. });
  142. this.img.cursor = "auto";
  143. }
  144. this.update();
  145. }
  146. /** 激活显示颜色 */
  147. _activeColor: SColor = new SColor("#00000033");
  148. get activeColor(): SColor {
  149. return this._activeColor;
  150. }
  151. set activeColor(v: SColor) {
  152. this._activeColor = v;
  153. this.update();
  154. }
  155. /** X 轴坐标 */
  156. get x(): number {
  157. return this.pos.x;
  158. }
  159. set x(v: number) {
  160. this.pos.x = v;
  161. this.$emit("changePos");
  162. this.update();
  163. }
  164. /** Y 轴坐标 */
  165. get y(): number {
  166. return this.pos.y;
  167. }
  168. set y(v: number) {
  169. this.pos.y = v;
  170. this.$emit("changePos");
  171. this.update();
  172. }
  173. /** icon 宽 */
  174. get sWidth(): number {
  175. return this.img.width;
  176. }
  177. set sWidth(v: number) {
  178. this.img.width = v;
  179. this.img.origin = new SPoint(
  180. this.img.width * 0.5,
  181. this.img.height * 0.5
  182. );
  183. this.changeAnchorPoint();
  184. this.update();
  185. }
  186. /** icon 高 */
  187. get sHeight(): number {
  188. return this.img.height;
  189. }
  190. set sHeight(v: number) {
  191. this.img.height = v;
  192. this.img.origin = new SPoint(
  193. this.img.width * 0.5,
  194. this.img.height * 0.5
  195. );
  196. this.changeAnchorPoint();
  197. this.update();
  198. }
  199. /** 是否显示锚点 */
  200. private _showAnchor: boolean = true;
  201. get showAnchor(): boolean {
  202. return this._showAnchor;
  203. }
  204. set showAnchor(v: boolean) {
  205. this._showAnchor = v;
  206. this.anchorList.forEach(t => {
  207. t.visible = v;
  208. });
  209. }
  210. /** 文本颜色 */
  211. private _color: SColor = new SColor();
  212. get color(): SColor {
  213. return this._color;
  214. } // Get color
  215. set color(v: SColor) {
  216. this._color = v;
  217. this.textItemList.forEach(item => {
  218. item.color = v;
  219. });
  220. this.update();
  221. }
  222. /** 文本字体 */
  223. private _font: SFont = new SFont("sans-serif", 12);
  224. get font(): SFont {
  225. return this._font;
  226. } // Get font
  227. set font(v: SFont) {
  228. this._font = v;
  229. this.textItemList.forEach((item: SBaseTextEdit, index: number) => {
  230. item.font = v;
  231. // item.moveTo(this.img.width * 0.5, v.size * (index - 0.125 - 0.5 * this.textItemList.length));
  232. });
  233. this.update();
  234. } // Set font
  235. /** 图像 */
  236. img: SBaseImageEdit = new SBaseImageEdit(this);
  237. /** 文本数组 */
  238. textItemList: SBaseTextEdit[] = [];
  239. /** 当前选中的文本item */
  240. curTextItem: SBaseTextEdit | null = null;
  241. /**
  242. * 构造体
  243. *
  244. * @param parent 父节点
  245. * @param data 锚点数据
  246. */
  247. constructor(parent: SGraphItem | null, data: Marker | null = null) {
  248. super(parent);
  249. this.showSelect = false;
  250. this.img.showSelect = false;
  251. this.data = data;
  252. } // Constructor
  253. /**
  254. * 如果 data 设置;初始化data
  255. */
  256. initData() {
  257. if (!this.data) return;
  258. if (this.data.size) {
  259. this.sWidth = this.data.size.width;
  260. this.sHeight = this.data.size.height;
  261. }
  262. this.img.connect("onMove", this, this.changeAnchorPoint.bind(this));
  263. const anchorPoint = [{ x: this.img.x, y: this.img.y, id: "" }];
  264. this.anchorList = anchorPoint.map(t => {
  265. let item = new SAnchorItem(this);
  266. if (t.id) {
  267. item.id = t.id;
  268. }
  269. item.moveTo(t.x, t.y);
  270. return item;
  271. });
  272. this.showAnchor = false;
  273. // 对文本数据进行处理
  274. if (
  275. this.data.style &&
  276. this.data.style.default &&
  277. this.data.style.default.textList
  278. ) {
  279. const textList = this.data.style.default.textList;
  280. if (textList.length) {
  281. const textItemList: any[] = [];
  282. textList.forEach((item: any, index: number) => {
  283. let obj = new SBaseTextEdit(this, null);
  284. obj.propertyData = item;
  285. obj.text = item.text;
  286. if (item.pos) {
  287. obj.moveTo(item.pos.x, item.pos.x);
  288. } else {
  289. obj.moveTo(
  290. this.img.width * 0.5,
  291. -(this.font.size * 1.25 * 0.5) + index * 10
  292. );
  293. }
  294. obj.font.size = item.font;
  295. obj.isTransform = false;
  296. obj.showSelect = false;
  297. obj.color = new SColor(item.color);
  298. obj.connect("textSelect", this, this.textSelectChange);
  299. textItemList.push(obj);
  300. });
  301. this.textItemList = textItemList;
  302. }
  303. }
  304. this.img.url = this.data.style.default.url;
  305. this.x = this.data.pos.x;
  306. this.y = this.data.pos.y;
  307. this.moveable = true;
  308. this.selectable = true;
  309. } // Function initData()
  310. /**
  311. * 添加文本
  312. *
  313. * @param item 文本图例
  314. */
  315. addTextItem(item: SBaseTextEdit) {
  316. this.textItemList.push(item);
  317. } // Function addTextItem
  318. /**
  319. * 删除文本
  320. *
  321. * @param index 索引
  322. */
  323. removeTextItem(index: number) {
  324. let [delteItem] = this.textItemList.splice(index, 1);
  325. if (this.scene) {
  326. this.scene.removeItem(delteItem);
  327. }
  328. } // Function removeTextItem
  329. /**
  330. * 计算并移动锚点的位置
  331. */
  332. changeAnchorPoint(): void {
  333. // 判断是否有锚点
  334. if (this.anchorList.length) {
  335. let anchorPoint = [
  336. { x: this.img.x, y: this.img.y },
  337. { x: this.img.x, y: this.img.y },
  338. { x: this.img.x, y: this.img.y },
  339. { x: this.img.x, y: this.img.y }
  340. ];
  341. this.anchorList.forEach((item, index) => {
  342. item.moveTo(anchorPoint[index].x, anchorPoint[index].y);
  343. });
  344. }
  345. }
  346. /**
  347. * 选中的文本item变化
  348. */
  349. textSelectChange(item: SBaseTextEdit): void {
  350. this.curTextItem = item;
  351. } // Function textSelectChange()
  352. /**
  353. * 鼠标按下事件
  354. *
  355. * @param event 事件对象
  356. * @return 是否处理事件
  357. */
  358. onMouseDown(event: SMouseEvent): boolean {
  359. this.curTextItem = null;
  360. if (this.status == SItemStatus.Normal) {
  361. super.onMouseDown(event);
  362. return true;
  363. } else if (this.status == SItemStatus.Edit) {
  364. // @ts-ignore
  365. const ce = SGraphItem.toChildMouseEvent(this, event);
  366. return super.onMouseDown(ce);
  367. }
  368. return true;
  369. }
  370. /**
  371. * 鼠标抬起事件
  372. *
  373. * @param event 事件对象
  374. * @return 是否处理事件
  375. */
  376. onMouseUp(event: SMouseEvent): boolean {
  377. if (this.status == SItemStatus.Edit) {
  378. return true;
  379. }
  380. super.onMouseUp(event);
  381. return true;
  382. }
  383. /**
  384. * 宽高发发生变化
  385. *
  386. * @param oldSize 改之前的大小
  387. * @param newSize 改之后大小
  388. */
  389. onResize(oldSize: SSize, newSize: SSize) {
  390. // console.log(arguments);
  391. } // Function onResize()
  392. /**
  393. * 鼠标双击事件
  394. *
  395. * @param event 鼠标事件
  396. * @return 是否处理事件
  397. */
  398. onDoubleClick(event: SMouseEvent): boolean {
  399. // 如果位show状态 双击改对象则需改为编辑状态
  400. if (SItemStatus.Normal == this.status) {
  401. this.status = SItemStatus.Edit;
  402. this.grabItem(this);
  403. } else if (SItemStatus.Edit == this.status) {
  404. this.status = SItemStatus.Normal;
  405. this.releaseItem();
  406. }
  407. this.update();
  408. return true;
  409. }
  410. /**
  411. * 宽高发生变化
  412. *
  413. * @return SRect 所有子对象的并集
  414. */
  415. boundingRect(): SRect {
  416. let rect = this.img
  417. .boundingRect()
  418. .adjusted(this.img.pos.x, this.img.pos.y, 0, 0);
  419. if (this.showText) {
  420. this.textItemList.forEach(item => {
  421. rect = rect.unioned(
  422. item.boundingRect().adjusted(item.pos.x, item.pos.y, 0, 0)
  423. );
  424. });
  425. }
  426. return rect.adjusted(-5, -5, 10, 10);
  427. }
  428. /**
  429. * Item 绘制操作
  430. *
  431. * @param painter 绘制对象
  432. */
  433. onDraw(painter: SPainter): void {
  434. const rect = this.boundingRect();
  435. const lw = painter.toPx(1);
  436. // 编辑态和选中态出现绘制区域
  437. if (this.status == SItemStatus.Edit || this.selected) {
  438. // doto 如果子元素被选中
  439. painter.pen.lineWidth = lw;
  440. painter.pen.lineDash = [3 * lw, 7 * lw];
  441. painter.pen.color = SColor.Black;
  442. painter.brush.color = SColor.Transparent;
  443. painter.drawRect(rect);
  444. }
  445. // 编辑态出现四个角的圆点
  446. if (this.status == SItemStatus.Edit) {
  447. painter.pen.lineDash = [];
  448. painter.brush.color = SColor.White;
  449. painter.drawCircle(rect.x, rect.y, 5 * lw);
  450. painter.drawCircle(rect.right, rect.bottom, 5 * lw);
  451. painter.drawCircle(rect.x, rect.bottom, 5 * lw);
  452. painter.drawCircle(rect.right, rect.y, 5 * lw);
  453. }
  454. if (this.isActive) {
  455. painter.pen.color = SColor.Transparent;
  456. painter.brush.color = this.activeColor;
  457. // 是否选中
  458. if (this.selected) {
  459. painter.shadow.shadowBlur = 10;
  460. painter.shadow.shadowColor = this.activeColor;
  461. painter.shadow.shadowOffsetX = 5;
  462. painter.shadow.shadowOffsetY = 5;
  463. painter.drawCircle(
  464. this.img.x,
  465. this.img.y,
  466. (this.sWidth / 2.0 + 3) * 1.25
  467. );
  468. } else {
  469. painter.drawCircle(
  470. this.img.x,
  471. this.img.y,
  472. this.sWidth / 2.0 + 3
  473. );
  474. }
  475. } else {
  476. // 是否选中
  477. if (this.selected) {
  478. painter.pen.color = SColor.Transparent;
  479. painter.brush.color = SColor.Transparent;
  480. painter.shadow.shadowBlur = 10;
  481. painter.shadow.shadowColor = new SColor(`#00000033`);
  482. painter.shadow.shadowOffsetX = 5;
  483. painter.shadow.shadowOffsetY = 5;
  484. painter.drawCircle(this.img.x, this.img.y, this.sWidth / 2.0);
  485. }
  486. }
  487. } // Function onDraw()
  488. /**
  489. * 返回对象储存的相关数据
  490. *
  491. * @return 相关数据
  492. */
  493. toData(): any {
  494. if (this.data) {
  495. if (this.data.size) {
  496. this.data.size.width = this.sWidth;
  497. this.data.size.height = this.sHeight;
  498. }
  499. this.data.style.default.text = JSON.stringify(this.textItemList);
  500. this.data.pos.x = this.pos.x;
  501. this.data.pos.y = this.pos.y;
  502. this.data.style.default.zorder = this.zOrder;
  503. this.data.style.default.url = this.img.url;
  504. }
  505. const anchorPoint = [{ x: this.img.x, y: this.img.y, id: "" }];
  506. this.anchorList = anchorPoint.map(t => {
  507. let item = new SAnchorItem(this);
  508. if (t.id) {
  509. item.id = t.id;
  510. }
  511. item.moveTo(t.x, t.y);
  512. return item;
  513. });
  514. // this.textItemList.font.size = this.data.style.default.font || 12;
  515. // this.img.url = this.data.style.default.url;
  516. if (this.data) {
  517. this.x = this.data.pos.x;
  518. this.y = this.data.pos.y;
  519. }
  520. } // Function toData()
  521. } // Class SBaseIconTextEdit