/* * ********************************************************************************************************************* * * !! * .F88X * X8888Y * .}888888N; * i888888N; .:! .I$WI: * R888888I .'N88~ i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8& * .R888888I .;N8888~ .X8' "8I.!,/8" !%NY8`"8I8~~8>,88I * +888888N; .8888888Y "&&8Y.}8, * ./888888N; .R888888Y .'}~ .>}'.`+> i}! "i' +/' .'i~ !11,.:">, .~]! .i}i * ~888888%: .I888888l .]88~`1/iY88Ii+1'.R$8$8]"888888888> Y8$ W8E X8E W8888'188Il}Y88$* * 18888888 E8888881 .]W%8$`R8X'&8%++N8i,8N%N8+l8%` .}8N:.R$RE%N88N%N$K$R 188,FE$8%~Y88I * .E888888I .i8888888' .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~ * 8888888I .,N888888~ ~88i"8W,!N8*.I88.}888%F,i$88"F88" 888:E8X.>88!i88>`888*.}Fl1]*}1YKi' * i888888N' I888Y ]88;/EX*IFKFK88X K8R .l8W 88Y ~88}'88E&%8W.X8N``]88!.$8K .:W8I * .i888888N; I8Y .&8$ .X88! i881.:%888>I88 ;88] +88+.';;;;:.Y88X 18N.,88l .+88/ * .:R888888I * .&888888I Copyright (c) 2016-2020. 博锐尚格科技股份有限公司 * ~8888' * .!88~ All rights reserved. * * ********************************************************************************************************************* */ import { SGraphItem } from "./SGraphItem"; import { SObject } from "@persagy-web/base"; import { SGraphLayoutType } from "./enums/SGraphLayoutType"; import { SOrderSetType } from "./enums/SOrderSetType"; /** * 基本选择器 * * @author 郝建龙 */ export class SGraphSelectContainer extends SObject { /** 选择对象list */ private itemList: SGraphItem[] = []; /** 统计选中item的数量 */ get count(): number { return this.itemList.length; } /** 置顶zorder增加基数 */ private radix: number = 0.001; /** * 构造体 * */ constructor() { super(); } // Constructor /** * 添加item到list * * @param item 当前选中的item * */ addItem(item: SGraphItem): void { for (let i = 0; i < this.itemList.length; i++) { if (this.itemList[i] == item) { return; } } item.selected = true; this.itemList.push(item); this.$emit("listChange", this.itemList); } // Function addItem() /** * 清空再添加(事件+复制数组) * * @param item 当前选中的item * */ setItem(item: SGraphItem): void { this.itemList.forEach((t: SGraphItem): void => { t.selected = false; }); this.itemList.length = 0; item.selected = true; this.itemList.push(item); this.$emit("listChange", this.itemList); } // Function setItem() /** * 清空选择对象 * * */ clear(): void { this.itemList.forEach((t: SGraphItem): void => { t.selected = false; }); this.itemList.length = 0; this.$emit("listChange", this.itemList); } // Function clear() /** * 切换选择对象 * * @param item 当前选中的item * */ toggleItem(item: SGraphItem): void { for (let i = 0; i < this.itemList.length; i++) { if (this.itemList[i] == item) { this.itemList[i].selected = false; this.itemList.splice(i, 1); this.$emit("listChange", this.itemList, item); return; } } // 多选时,父级item需要一致 if (this.itemList.length) { if (item.parent != this.itemList[0].parent) { return; } } item.selected = true; this.itemList.push(item); this.$emit("listChange", this.itemList); } // Function toggleItem() /** * 对齐 * * @param type 对齐方式 * */ layout(type: SGraphLayoutType): void { if (this.itemList.length < 2) { return; } switch (type) { case SGraphLayoutType.Left: this.alignLeft(); break; case SGraphLayoutType.Bottom: this.alignBottom(); break; case SGraphLayoutType.Center: this.alignCenter(); break; case SGraphLayoutType.Horizontal: this.alignHorizontal(); break; case SGraphLayoutType.Middle: this.alignMiddle(); break; case SGraphLayoutType.Right: this.alignRight(); break; case SGraphLayoutType.Top: this.alignTop(); break; case SGraphLayoutType.Vertical: this.alignVertical(); break; default: console.log("对齐类型不存在"); break; } } // Function layout() /** * 图层操作 * * @param type 操作类型 * */ setOrder(type: SOrderSetType): void { if (this.itemList.length < 1) { return; } switch (type) { case SOrderSetType.Top: this.setTop(); break; case SOrderSetType.Bottom: this.setBottom(); break; case SOrderSetType.After: this.setAfter(); break; case SOrderSetType.Before: this.setBefore(); break; default: console.log("图层操作类型不存在"); break; } } // Function setOrder() /** * 左对齐 * * */ private alignLeft(): void { let standardItem = this.itemList[0]; // 计算第一个外接矩阵左上角坐标在场景中的坐标 let p = standardItem.mapToScene( standardItem.boundingRect().x, standardItem.boundingRect().y ); for (let i = 1; i < this.itemList.length; i++) { let curItem = this.itemList[i]; if (curItem.moveable) { // 将p转换为当前item中的坐标 let p1 = curItem.mapFromScene(p.x, p.y); // 根据等式差值相等 newboundx - oldboundx = newposx - oldposx => newposx = newboundx - oldboundx + oldposx curItem.x = (p1.x - curItem.boundingRect().x) * curItem.inverseScale + curItem.x; } } } // Function alignLeft() /** * 顶对齐 * * */ private alignTop(): void { let standardItem = this.itemList[0]; let p = standardItem.mapToScene( standardItem.boundingRect().x, standardItem.boundingRect().y ); for (let i = 1; i < this.itemList.length; i++) { let curItem = this.itemList[i]; if (curItem.moveable) { let p1 = curItem.mapFromScene(p.x, p.y); curItem.y = (p1.y - curItem.boundingRect().y) * curItem.inverseScale + curItem.y; } } } // Function alignTop() /** * 右对齐 * * */ private alignRight(): void { let standardItem = this.itemList[0]; let p = standardItem.mapToScene( standardItem.boundingRect().right, standardItem.boundingRect().bottom ); for (let i = 1; i < this.itemList.length; i++) { let curItem = this.itemList[i]; if (curItem.moveable) { let p1 = curItem.mapFromScene(p.x, p.y); curItem.x = (p1.x - curItem.boundingRect().right) * curItem.inverseScale + curItem.x; } } } // Function alignRight() /** * 底对齐 * * */ private alignBottom(): void { let standardItem = this.itemList[0]; let p = standardItem.mapToScene( standardItem.boundingRect().right, standardItem.boundingRect().bottom ); for (let i = 1; i < this.itemList.length; i++) { let curItem = this.itemList[i]; if (curItem.moveable) { let p1 = curItem.mapFromScene(p.x, p.y); curItem.y = (p1.y - curItem.boundingRect().bottom) * curItem.inverseScale + curItem.y; } } } // Function alignBottom() /** * 水平居中对齐 * * */ private alignCenter(): void { // 第一个选中的item即为基准对象 let standardItem = this.itemList[0]; // 基准对象的中心点 let center = standardItem.boundingRect().center(); // 中心点转换为场景坐标 let p = standardItem.mapToScene(center.x, center.y); for (let i = 1; i < this.itemList.length; i++) { let curItem = this.itemList[i]; if (curItem.moveable) { let p1 = curItem.mapFromScene(p.x, p.y); // 根据等式差值相等 newcenterx - oldcenterx = newposx - oldposx => newposx = newcenterx - oldcenterx + oldposx curItem.x = (p1.x - curItem.boundingRect().center().x) * curItem.inverseScale + curItem.x; } } } // Function alignCenter() /** * 垂直居中对齐 * * */ private alignMiddle(): void { // 第一个选中的item即为基准对象 let standardItem = this.itemList[0]; // 基准对象的中心点 let center = standardItem.boundingRect().center(); // 中心点转换为场景坐标 let p = standardItem.mapToScene(center.x, center.y); for (let i = 1; i < this.itemList.length; i++) { let curItem = this.itemList[i]; if (curItem.moveable) { let p1 = curItem.mapFromScene(p.x, p.y); curItem.y = (p1.y - curItem.boundingRect().center().y) * curItem.inverseScale + curItem.y; } } } // Function alignMiddle() /** * 垂直分布 * * */ private alignVertical(): void { if (this.itemList.length < 3) { return; } for (let i = 0; i < this.itemList.length - 1; i++) { for (let j = 0; j < this.itemList.length - 1 - i; j++) { let curItemCenter = this.itemList[j].boundingRect().center(); let nextItemCenter = this.itemList[j + 1] .boundingRect() .center(); let curCenterY = this.itemList[j].mapToScene( curItemCenter.x, curItemCenter.y ).y; let nextCenterY = this.itemList[j + 1].mapToScene( nextItemCenter.x, nextItemCenter.y ).y; if (curCenterY > nextCenterY) { let temp = this.itemList[j]; this.itemList[j] = this.itemList[j + 1]; this.itemList[j + 1] = temp; } } } let top = this.itemList[0]; let bottom = this.itemList[this.itemList.length - 1]; let topCenter = top.boundingRect().center(); let bottomCenter = bottom.boundingRect().center(); let leftToRight = bottom.mapToScene(bottomCenter.x, bottomCenter.y).y - top.mapToScene(topCenter.x, topCenter.y).y; let average = leftToRight / (this.itemList.length - 1); for (let k = 1; k < this.itemList.length - 1; k++) { let curItem = this.itemList[k]; if (curItem.moveable) { let p1 = top.mapToScene( top.boundingRect().center().x, top.boundingRect().center().y ); let p2 = curItem.mapFromScene(p1.x, p1.y + average * k); curItem.y = (p2.y - curItem.boundingRect().center().y) * curItem.inverseScale + curItem.y; } } } // Function alignVertical() /** * 水平分布 * * */ private alignHorizontal(): void { if (this.itemList.length < 3) { return; } for (let i = 0; i < this.itemList.length - 1; i++) { for (let j = 0; j < this.itemList.length - 1 - i; j++) { let curItemCenter = this.itemList[j].boundingRect().center(); let nextItemCenter = this.itemList[j + 1] .boundingRect() .center(); let curCenterX = this.itemList[j].mapToScene( curItemCenter.x, curItemCenter.y ).x; let nextCenterX = this.itemList[j + 1].mapToScene( nextItemCenter.x, nextItemCenter.y ).x; if (curCenterX > nextCenterX) { let temp = this.itemList[j]; this.itemList[j] = this.itemList[j + 1]; this.itemList[j + 1] = temp; } } } let left = this.itemList[0]; let right = this.itemList[this.itemList.length - 1]; let leftCenter = left.boundingRect().center(); let rightCenter = right.boundingRect().center(); let leftToRight = right.mapToScene(rightCenter.x, rightCenter.y).x - left.mapToScene(leftCenter.x, leftCenter.y).x; let average = leftToRight / (this.itemList.length - 1); for (let k = 1; k < this.itemList.length - 1; k++) { let curItem = this.itemList[k]; if (curItem.moveable) { let p1 = left.mapToScene( left.boundingRect().center().x, left.boundingRect().center().y ); let p2 = curItem.mapFromScene(p1.x + average * k, p1.y); // 根据等式 newposx - oldposx = newcenterx - oldcenterx curItem.x = (p2.x - curItem.boundingRect().center().x) * curItem.inverseScale + curItem.x; } } } // Function alignHorizontal() // 修改层级操作步骤: // 排序(保持相对层级不变) // children里边要取 整数部分相同的 点:children是已经排好序的 // 然后再取最大值 /** * 置顶 * * */ private setTop(): void { const arr: SGraphItem[] = this.sortItemList(this.itemList, true); // 按顺序zOrder增加 arr.forEach(it => { let max = it.zOrder; if (it.parent) { it.parent.children.forEach(item => { if ( Number(max.toFixed()) == Number(item.zOrder.toFixed()) ) { if (item.zOrder > max) { max = item.zOrder; } } }); it.zOrder = max + this.radix; } }); } // Function setTop() /** * 置底 * * */ private setBottom(): void { const arr: SGraphItem[] = this.sortItemList(this.itemList, false); // 按顺序zOrder增加 arr.forEach(it => { let min = it.zOrder; if (it.parent) { it.parent.children.forEach(item => { if ( Number(min.toFixed()) == Number(item.zOrder.toFixed()) ) { if (item.zOrder < min) { min = item.zOrder; } } }); it.zOrder = min - this.radix; } }); } // Function setBottom() /** * 下移一层zorder减小 * * */ private setBefore(): void { const arr: SGraphItem[] = this.sortItemList(this.itemList, false); arr.forEach(it => { if (it.parent) { const min = it.zOrder; let temp = it.parent.children .map(child => { if ( Number(child.zOrder.toFixed()) == Number(min.toFixed()) ) { return child.zOrder; } }) .filter(c => c); temp = [...new Set(temp)]; // 当前层有多个 const index = temp.indexOf(it.zOrder); if (index <= 1) { // 当前item 索引为1时 将当前item放至第一个前边 // @ts-ignore it.zOrder = temp[0] - this.radix; } else if (index > 1) { // 当前item 索引大于等于2,将当前item放至前两个中间 // @ts-ignore it.zOrder = (temp[index - 1] + temp[index - 2]) / 2; } } }); } // Function setAfter() /** * 上移一层zorder增加 * * */ private setAfter(): void { const arr: SGraphItem[] = this.sortItemList(this.itemList, false); arr.forEach(it => { if (it.parent) { const max = it.zOrder; let temp = it.parent.children .map(child => { if ( Number(child.zOrder.toFixed()) == Number(max.toFixed()) ) { return child.zOrder; } }) .filter(c => c); temp = [...new Set(temp)].reverse(); // 当前层有多个 const index = temp.indexOf(it.zOrder); if (index <= 1) { // 当前item 索引为1时 将当前item放至第一个前边 // @ts-ignore it.zOrder = temp[0] + this.radix; } else if (index > 1) { // 当前item 索引大于等于2,将当前item放至前两个中间 // @ts-ignore it.zOrder = (temp[index - 1] + temp[index - 2]) / 2; } } }); } // Function setBefore() /** * 数组排序 * * @param arr 排序前的数组 * @param flag 正序or逆序 * @return list 排序后的数组 * */ sortItemList(arr: SGraphItem[], flag: boolean = true): SGraphItem[] { const list: SGraphItem[] = arr.map(t => t); list.sort(this.compare("zOrder", flag)); return list; } // Function sortItemList() /** * 按照某个属性排序 * * @param prop 属性 * @param flag 默认正序 * */ private compare(prop: string, flag: boolean) { const f = flag ? 1 : -1; // eslint-disable-next-line @typescript-eslint/explicit-function-return-type return (a: any, b: any) => { a = a[prop]; b = b[prop]; if (a < b) { return f * -1; } if (a > b) { return f * 1; } return 0; }; } // Function compare() } // Class SGraphSelectContainer