/* * ********************************************************************************************************************* * * !! * .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 { SGraphDeleteListCommand, SGraphEditScene, SGraphEdit } from "@persagy-web/edit"; import { SMouseEvent } from "@persagy-web/base/lib"; import { SArrowStyleType, SPoint, SRect } from "@persagy-web/draw"; import { SItemStatus, SRectSelectItem } from "@persagy-web/big/lib"; import { SGraphItem, SGraphSelectContainer, SOrderSetType } from "@persagy-web/graph/lib/"; import { SBaseArrow, SBaseExplainEdit, SBasePipe } from "./"; import { SBaseArrowPolyEdit } from "./items/SBaseArrowPolyEdit"; import { SGraphAddListCommand } from "@persagy-web/edit/lib/commands/SGraphAddListCommand"; /** * big-edit 场景 * * @author 韩耀龙 */ export class SBaseEditScene extends SGraphEditScene { /** 图例节点 */ Nodes: any = []; // 图例节点,所有与工程信息化相关的图例(图标类型与区域) // 与工程信息无关的标识对象(增加文本注释,图上的图片说明) /** 图例节点 */ Markers: any = []; /** 管线对象 */ Relations: any = []; /** 复制的对象 */ copyString: any[] = []; /** 选中的对象 */ grabItem: null | SGraphEdit | SGraphItem = null; /** * 构造函数 * */ constructor() { super(); } /** * 新增基础类注释 * * @param event 鼠标事件参数 * @return 新增的基础类注释 */ addExplainItem(event: SMouseEvent): SBaseExplainEdit { const data = { /** 名称 */ name: "基础注释文本", /** 图标 */ type: "Text", /** 位置 */ pos: { x: event.x, y: event.y }, /** 由应用自己定义 */ properties: { type: "BaseExplain" }, style: { default: { text: "请在右侧属性栏输入文字!", color: "#646c73", font: 14, backgroundcolor: "#f7f9facc" } } }; const item = new SBaseExplainEdit(null, data); item.moveTo(event.x, event.y); item.selectable = true; item.moveable = true; this.addItem(item); this.grabItem = null; item.connect("onContextMenu", this, this.getItem); this.finishCreated(item); return item; } /** * 新增基础箭头(折线) * * @param event 鼠标事件 * @return 新增的基础箭头(折线) */ addPolyLineArrow(event: SMouseEvent): SBaseArrow { const data = { name: "基础箭头", type: "Arrow", pos: { x: 0, y: 0 }, properties: { type: "BaseArrow" }, style: { outLine: [{ x: event.x, y: event.y }], begin: SArrowStyleType.None, //开端箭头样式 end: SArrowStyleType.None, //结尾箭头样式 isMove: true, //是否可以移动 default: {} } }; const item = new SBaseArrow(null, data); item.status = SItemStatus.Create; item.selectable = true; this.addItem(item); this.grabItem = item; item.connect("finishCreated", this, this.finishCreated); item.connect("onContextMenu", this, this.getItem); // view 必须存在 if (this.view) { this.view.update(); } return item; } /** * 新增基础箭头(多边形) * * @param event 鼠标事件 * @return 新增的基础箭头(多边形) */ addPolygonArrow(event: SMouseEvent): SBaseArrowPolyEdit { const data = { /** 名称 */ name: "多边形箭头", /** 图标(Image),线类型(Line) */ type: "ArrowPolygon", /** 缩放比例(Image),线类型(Line) */ scale: { x: 1, y: 1, z: 1 }, /** 缩放比例(Image),线类型(Line) */ rolate: { x: 0, y: 0, z: 0 }, /** 位置 */ pos: { x: 0, y: 0 }, /** 由应用自己定义 */ properties: { type: "BaseArrowPolygon" // 自定义类型用于区分mark与node }, style: { line: [{ x: event.x, y: event.y }], default: {} } }; const item = new SBaseArrowPolyEdit(null, data); item.status = SItemStatus.Create; item.selectable = true; this.addItem(item); this.grabItem = item; item.connect("finishCreated", this, this.finishCreated); item.connect("onContextMenu", this, this.getItem); // view 必须存在 if (this.view) { // 视图存在缩放比例,箭头宽度随缩放比例改变 if (this.view?.scale) { item.arrowWidth = item.arrowWidth / this.view.scale; } this.view.update(); } return item; } // /** // * 添加基本设备 item // * // * @param event 鼠标事件 // * @param legendObj 图例样式 // */ // addEuqipment(event: SMouseEvent, legendObj: any): void { // const data = { // nodeId: uuid(), // /** 名称 */ // name: '基础设备', // /** 返回物理世界对象 ID 列表 */ // attachObjectIds: [], // size: { width: 50, height: 50 }, // /** 图标 (Image),线类型 (Line) */ // type: "Image", // /** 位置 */ // pos: { x: event.x, y: event.y }, // /** 由应用自己定义 */ // properties: { // type: "BaseEquipment", // infoMsgList: [{ // }] // }, // style: { // default: { // strokecolor: "#c0ccda", // url: require('./../../../assets/images/equip/' + legendObj.url), // } // } // } // const item = new SBaseEquipment(null, data); // item.status = SItemStatus.Create; // this.addItem(item); // item.selectable = true; // item.moveable = true; // this.grabItem = item; // this.finishCreated(item) // item.connect("onContextMenu", this, this.getItem); // if (this.view) { // this.view.update(); // } // } /** * 新增管道 * * @param event 鼠标事件 * @return 新增的管道 */ addBasePipe(event: SMouseEvent, legendObj: any): SBasePipe { const anc = this.isAdsorb ? this.clickIsAnchor(event) :null; // 锚点时否存在 if (anc) { const p = anc.mapToScene(0, 0); anc.isConnected = true; event.x = p.x; event.y = p.y; } const data = { name: legendObj.name, graphElementId: legendObj.id, lineType: "", node1Id: "", node2Id: "", anchor1Id: "", anchor2Id: "", pointList: [{ x: event.x, y: event.y }], properties: { type: "BasePipe" }, style: { default: { strokeColor: legendObj.color, lineWidth: 4 } } }; const item = new SBasePipe(null, data); item.status = SItemStatus.Create; item.selectable = true; this.addItem(item); this.grabItem = item; // 起始锚点 item.startAnchor = anc; // 锚点事件绑定 if (anc) { anc.parent?.connect("changePos", item, item.changePos); item.anchor1Id = anc.id; item.node1Id = anc.parent ? anc.parent.nodeId : ""; } item.connect("finishCreated", this, this.finishCreated); item.connect("onContextMenu", this, this.getItem); if (this.view) { this.view.update(); } return item; } /** * 重做 */ redo(): void { if (this.grabItem && this.grabItem instanceof SGraphEdit) { this.grabItem.redo(); } else { this.undoStack.redo(); } } /** * 撤销 */ undo(): void { if (this.grabItem && this.grabItem instanceof SGraphEdit) { this.grabItem.undo(); } else { this.undoStack.undo(); } } /** * 删除 * * @return 删除的图例 */ deleteItem(itemArr: SGraphItem[] = []): any { let itemList: SGraphItem[] = []; if (itemArr && itemArr.length && itemArr[0]) { itemList = [...itemArr]; } else { if (this.selectContainer.count == 0) { return []; } itemList = this.selectContainer.itemList; this.undoStack.push( new SGraphDeleteListCommand(this, [...itemList]) ); } // 推入 undo/redo 栈 itemList.forEach((element: any) => { this.removeItem(element); }); // view 必须存在 if (this.view) { this.view.update(); } return itemList; } /** * 框选 */ addRectSelect(event: SMouseEvent): void { let point = new SPoint(event.x, event.y); let rect = new SRectSelectItem(null, point); this.addItem(rect); this.grabItem = rect; } /** * 计算框选交集 * * @param ctrl 是否点击ctrl */ groupSelect(ctrl: boolean) { // 判断当前图例是否为选中框 if (this.grabItem instanceof SRectSelectItem) { const rect = this.grabItem.boundingRect(); this.arrToSelect(this.root.children, rect); } } /** * 选中item:框选 * * @param arr 实例数组 * @param rect 框选矩形区域 */ private arrToSelect(arr: SGraphItem[], rect: SRect) { // 数组不为空 if (Array.isArray(arr) && arr.length) { // 对框选范围内的对象高亮显示 arr.forEach(t => { if (!(t instanceof SGraphSelectContainer) && t.parent) { if (t.visible) { let temp = t.boundingRect(); let lefttop = t.mapToScene(temp.left, temp.top); let rightbottom = t.mapToScene(temp.right, temp.bottom); let r = new SRect(lefttop, rightbottom); if (rect.isIn(r)) { this.selectContainer.toggleItem(t); } } } }); } } ///////////////////////////////////////////////////////////////////// // 鼠标事件 /** * 鼠标左键按下 * * @param event 鼠标事件参数 */ onMouseDown(event: SMouseEvent): any { if (!super.onMouseDown(event) && 1 == event.buttons) { this.addRectSelect(event); } } /** * 鼠标抬起 * * @param event 鼠标事件参数 */ onMouseUp(event: SMouseEvent): boolean { // grabItem 不为 null if (this.grabItem) { // 鼠标抬起时,如果grabItem为框选则删除框选item if (this.grabItem instanceof SRectSelectItem) { this.removeItem(this.grabItem); this.groupSelect(false); this.grabItem = null; // view 不为空 if (this.view) { this.view.update(); } return true; } return this.grabItem.onMouseUp(event); } return super.onMouseUp(event); } /** * 复制 */ copy(): void { const itemList = this.save(false); // itemList 复制数据不为空 if (itemList) { // 删除对应得id itemList.markers.map((item: any) => { delete item.id; delete item.graphId; delete item.markerId; return item; }); // 删除对应得id itemList.nodes.map((item: any) => { delete item.id; delete item.graphId; delete item.markerId; return item; }); // 删除对应得id itemList.relations.map((item: any) => { delete item.id; delete item.graphId; delete item.markerId; return item; }); this.copyString = itemList; // 获取input dom const input = document.createElement("input"); input.setAttribute("id", "COPYINPUT"); input.value = JSON.stringify(this.copyString); sessionStorage.setItem("copyString", input.value); document.body.appendChild(input); input.select(); document.execCommand("copy"); input.style.display = "none"; console.log(input.value, Date.now()); document.body.removeChild(input); } } /** * 添加多个item命令 * * @param itemList 鼠标事件对象 */ addListCommand(itemList: SGraphEdit[]): void { this.undoStack.push(new SGraphAddListCommand(this, itemList)); } /** * 图例置顶、置底 * * @param type 设置类型 */ setOrder(type: string) { this.selectContainer.setOrder(SOrderSetType[type]); } /** * 设置管线结束锚点 */ setTipeEndanchor(event: SMouseEvent): void { if (this.grabItem instanceof SBasePipe) { const anc = this.clickIsAnchor(event); if (anc) { const p = anc.mapToScene(0, 0); anc.isConnected = true; event.x = p.x; event.y = p.y; // 判断当前是否为编辑状态 if (this.grabItem.status == SItemStatus.Create) { // pointList 长度不能为空 if (this.grabItem.pointList.length) { this.grabItem.endAnchor = anc; anc.parent?.connect( "changePos", this.grabItem, this.grabItem.changePos ); } this.grabItem.anchor2Id = anc.id; this.grabItem.node2Id = anc.parent.nodeId; this.grabItem.onMouseDown(event); this.grabItem.status = SItemStatus.Normal; this.finishCreated(this.grabItem); return; } } this.grabItem.onMouseDown(event); } } /** * 获取item (常用与场景外的调用F) * * @param isAll 是否为全部item数据 * @returns 返回保存的数据接口 */ save(isAll: boolean = true): any {} }