SGraphSelectContainer.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. import { SGraphItem } from "./SGraphItem";
  2. import { SObject } from "@saga-web/base/lib";
  3. import { SGraphLayoutType } from "./enums/SGraphLayoutType";
  4. /**
  5. * 基本选择器
  6. *
  7. * @author 郝建龙
  8. */
  9. export class SGraphSelectContainer extends SObject {
  10. /** 选择对象list */
  11. private itemList: SGraphItem[] = [];
  12. /** 统计选中item的数量 */
  13. get count(): number {
  14. return this.itemList.length;
  15. }
  16. /**
  17. * 构造体
  18. * */
  19. constructor() {
  20. super();
  21. } // Constructor
  22. /**
  23. * 添加item到list
  24. *
  25. * @param item 当前选中的item
  26. * */
  27. addItem(item: SGraphItem): void {
  28. for (let i = 0; i < this.itemList.length; i++) {
  29. if (this.itemList[i] == item) {
  30. return;
  31. }
  32. }
  33. item.selected = true;
  34. this.itemList.push(item);
  35. this.$emit("listChange", this.itemList);
  36. } // Function addItem()
  37. /**
  38. * 清空再添加(事件+复制数组)
  39. *
  40. * @param item 当前选中的item
  41. * */
  42. setItem(item: SGraphItem): void {
  43. this.itemList.forEach((t: SGraphItem): void => {
  44. t.selected = false;
  45. });
  46. this.itemList.length = 0;
  47. item.selected = true;
  48. this.itemList.push(item);
  49. this.$emit("listChange", this.itemList);
  50. } // Function setItem()
  51. /**
  52. * 清空选择对象
  53. *
  54. * */
  55. clear(): void {
  56. this.itemList.forEach((t: SGraphItem): void => {
  57. t.selected = false;
  58. });
  59. this.itemList.length = 0;
  60. this.$emit("listChange", this.itemList);
  61. } // Function clear()
  62. /**
  63. * 切换选择对象
  64. *
  65. * @param item 当前选中的item
  66. * */
  67. toggleItem(item: SGraphItem): void {
  68. for (let i = 0; i < this.itemList.length; i++) {
  69. if (this.itemList[i] == item) {
  70. this.itemList[i].selected = false;
  71. this.itemList.splice(i, 1);
  72. this.$emit("listChange", this.itemList);
  73. return;
  74. }
  75. }
  76. // 多选时,父级item需要一致
  77. if (this.itemList.length) {
  78. if (item.parent != this.itemList[0].parent) {
  79. return;
  80. }
  81. }
  82. item.selected = true;
  83. this.itemList.push(item);
  84. this.$emit("listChange", this.itemList);
  85. } // Function toggleItem()
  86. /**
  87. * 对齐
  88. *
  89. * @param type 对齐方式
  90. * */
  91. layout(type: SGraphLayoutType): void {
  92. if (this.itemList.length < 2) {
  93. return;
  94. }
  95. switch (type) {
  96. case SGraphLayoutType.Left:
  97. this.alignLeft();
  98. break;
  99. case SGraphLayoutType.Bottom:
  100. this.alignBottom();
  101. break;
  102. case SGraphLayoutType.Center:
  103. this.alignCenter();
  104. break;
  105. case SGraphLayoutType.Horizontal:
  106. this.alignHorizontal();
  107. break;
  108. case SGraphLayoutType.Middle:
  109. this.alignMiddle();
  110. break;
  111. case SGraphLayoutType.Right:
  112. this.alignRight();
  113. break;
  114. case SGraphLayoutType.Top:
  115. this.alignTop();
  116. break;
  117. case SGraphLayoutType.Vertical:
  118. this.alignVertical();
  119. break;
  120. default:
  121. console.log("对齐类型不存在");
  122. break;
  123. }
  124. } // Function layout()
  125. /**
  126. * 左对齐
  127. *
  128. * */
  129. private alignLeft(): void {
  130. let standardItem = this.itemList[0];
  131. // 计算第一个外接矩阵左上角坐标在场景中的坐标
  132. let p = standardItem.mapToScene(
  133. standardItem.boundingRect().x,
  134. standardItem.boundingRect().y
  135. );
  136. for (let i = 1; i < this.itemList.length; i++) {
  137. let curItem = this.itemList[i];
  138. if (curItem.moveable) {
  139. // 将p转换为当前item中的坐标
  140. let p1 = curItem.mapFromScene(p.x, p.y);
  141. // 根据等式差值相等 newboundx - oldboundx = newposx - oldposx => newposx = newboundx - oldboundx + oldposx
  142. curItem.x = p1.x - curItem.boundingRect().x + curItem.x;
  143. }
  144. }
  145. } // Function alignLeft()
  146. /**
  147. * 顶对齐
  148. *
  149. * */
  150. private alignTop(): void {
  151. let standardItem = this.itemList[0];
  152. let p = standardItem.mapToScene(
  153. standardItem.boundingRect().x,
  154. standardItem.boundingRect().y
  155. );
  156. for (let i = 1; i < this.itemList.length; i++) {
  157. let curItem = this.itemList[i];
  158. if (curItem.moveable) {
  159. let p1 = curItem.mapFromScene(p.x, p.y);
  160. curItem.y = p1.y - curItem.boundingRect().y + curItem.y;
  161. }
  162. }
  163. } // Function alignTop()
  164. /**
  165. * 右对齐
  166. *
  167. * */
  168. private alignRight(): void {
  169. let standardItem = this.itemList[0];
  170. let p = standardItem.mapToScene(
  171. standardItem.boundingRect().right,
  172. standardItem.boundingRect().bottom
  173. );
  174. for (let i = 1; i < this.itemList.length; i++) {
  175. let curItem = this.itemList[i];
  176. if (curItem.moveable) {
  177. let p1 = curItem.mapFromScene(p.x, p.y);
  178. curItem.x = p1.x - curItem.boundingRect().right + curItem.x;
  179. }
  180. }
  181. } // Function alignRight()
  182. /**
  183. * 底对齐
  184. *
  185. * */
  186. private alignBottom(): void {
  187. let standardItem = this.itemList[0];
  188. let p = standardItem.mapToScene(
  189. standardItem.boundingRect().right,
  190. standardItem.boundingRect().bottom
  191. );
  192. for (let i = 1; i < this.itemList.length; i++) {
  193. let curItem = this.itemList[i];
  194. if (curItem.moveable) {
  195. let p1 = curItem.mapFromScene(p.x, p.y);
  196. curItem.y = p1.y - curItem.boundingRect().bottom + curItem.y;
  197. }
  198. }
  199. } // Function alignBottom()
  200. /**
  201. * 水平居中对齐
  202. *
  203. * */
  204. private alignCenter(): void {
  205. // 第一个选中的item即为基准对象
  206. let standardItem = this.itemList[0];
  207. // 基准对象的中心点
  208. let center = standardItem.boundingRect().center();
  209. // 中心点转换为场景坐标
  210. let p = standardItem.mapToScene(center.x, center.y);
  211. for (let i = 1; i < this.itemList.length; i++) {
  212. let curItem = this.itemList[i];
  213. if (curItem.moveable) {
  214. let p1 = curItem.mapFromScene(p.x, p.y);
  215. // 根据等式差值相等 newcenterx - oldcenterx = newposx - oldposx => newposx = newcenterx - oldcenterx + oldposx
  216. curItem.x =
  217. p1.x - curItem.boundingRect().center().x + curItem.x;
  218. }
  219. }
  220. } // Function alignCenter()
  221. /**
  222. * 垂直居中对齐
  223. *
  224. * */
  225. private alignMiddle(): void {
  226. // 第一个选中的item即为基准对象
  227. let standardItem = this.itemList[0];
  228. // 基准对象的中心点
  229. let center = standardItem.boundingRect().center();
  230. // 中心点转换为场景坐标
  231. let p = standardItem.mapToScene(center.x, center.y);
  232. for (let i = 1; i < this.itemList.length; i++) {
  233. let curItem = this.itemList[i];
  234. if (curItem.moveable) {
  235. let p1 = curItem.mapFromScene(p.x, p.y);
  236. curItem.y =
  237. p1.y - curItem.boundingRect().center().y + curItem.y;
  238. }
  239. }
  240. } // Function alignMiddle()
  241. /**
  242. * 垂直分布
  243. *
  244. * */
  245. private alignVertical(): void {
  246. if (this.itemList.length < 3) {
  247. return;
  248. }
  249. for (let i = 0; i < this.itemList.length - 1; i++) {
  250. for (let j = 0; j < this.itemList.length - 1 - i; j++) {
  251. let curItemCenter = this.itemList[j].boundingRect().center();
  252. let nextItemCenter = this.itemList[j + 1]
  253. .boundingRect()
  254. .center();
  255. let curCenterY = this.itemList[j].mapToScene(
  256. curItemCenter.x,
  257. curItemCenter.y
  258. ).y;
  259. let nextCenterY = this.itemList[j + 1].mapToScene(
  260. nextItemCenter.x,
  261. nextItemCenter.y
  262. ).y;
  263. if (curCenterY > nextCenterY) {
  264. let temp = this.itemList[j];
  265. this.itemList[j] = this.itemList[j + 1];
  266. this.itemList[j + 1] = temp;
  267. }
  268. }
  269. }
  270. let top = this.itemList[0];
  271. let bottom = this.itemList[this.itemList.length - 1];
  272. let topCenter = top.boundingRect().center();
  273. let bottomCenter = bottom.boundingRect().center();
  274. let leftToRight =
  275. bottom.mapToScene(bottomCenter.x, bottomCenter.y).y -
  276. top.mapToScene(topCenter.x, topCenter.y).y;
  277. let average = leftToRight / (this.itemList.length - 1);
  278. for (let k = 1; k < this.itemList.length - 1; k++) {
  279. let curItem = this.itemList[k];
  280. if (curItem.moveable) {
  281. let p1 = top.mapToScene(
  282. top.boundingRect().center().x,
  283. top.boundingRect().center().y
  284. );
  285. let p2 = curItem.mapFromScene(p1.x, p1.y + average * k);
  286. curItem.y =
  287. p2.y - curItem.boundingRect().center().y + curItem.y;
  288. }
  289. }
  290. } // Function alignVertical()
  291. /**
  292. * 水平分布
  293. *
  294. * */
  295. private alignHorizontal(): void {
  296. if (this.itemList.length < 3) {
  297. return;
  298. }
  299. for (let i = 0; i < this.itemList.length - 1; i++) {
  300. for (let j = 0; j < this.itemList.length - 1 - i; j++) {
  301. let curItemCenter = this.itemList[j].boundingRect().center();
  302. let nextItemCenter = this.itemList[j + 1]
  303. .boundingRect()
  304. .center();
  305. let curCenterX = this.itemList[j].mapToScene(
  306. curItemCenter.x,
  307. curItemCenter.y
  308. ).x;
  309. let nextCenterX = this.itemList[j + 1].mapToScene(
  310. nextItemCenter.x,
  311. nextItemCenter.y
  312. ).x;
  313. if (curCenterX > nextCenterX) {
  314. let temp = this.itemList[j];
  315. this.itemList[j] = this.itemList[j + 1];
  316. this.itemList[j + 1] = temp;
  317. }
  318. }
  319. }
  320. let left = this.itemList[0];
  321. let right = this.itemList[this.itemList.length - 1];
  322. let leftCenter = left.boundingRect().center();
  323. let rightCenter = right.boundingRect().center();
  324. let leftToRight =
  325. right.mapToScene(rightCenter.x, rightCenter.y).x -
  326. left.mapToScene(leftCenter.x, leftCenter.y).x;
  327. let average = leftToRight / (this.itemList.length - 1);
  328. for (let k = 1; k < this.itemList.length - 1; k++) {
  329. let curItem = this.itemList[k];
  330. if (curItem.moveable) {
  331. let p1 = left.mapToScene(
  332. left.boundingRect().center().x,
  333. left.boundingRect().center().y
  334. );
  335. let p2 = curItem.mapFromScene(p1.x + average * k, p1.y);
  336. // 根据等式 newposx - oldposx = newcenterx - oldcenterx
  337. curItem.x =
  338. p2.x - curItem.boundingRect().center().x + curItem.x;
  339. }
  340. }
  341. } // Function alignHorizontal()
  342. } // Class SGraphSelectContainer