import { Component, OnInit, ElementRef, ViewChild, AfterViewInit, Input } from '@angular/core'; import * as PIXI from 'pixi.js'; import { EventEmitter } from 'events'; import { EventManager } from '@angular/platform-browser'; import { OutlineFilter, OldFilmFilter } from 'pixi-filters'; import { AssetData, CanvasShareDataService, DisposalNodeData, FloorNodeData } from '../canvas-share-data.service'; import * as ObjectID from 'bson-objectid'; import { Charm } from './charm'; import { SinglePointIcon } from './model/singlePointIcon'; import { GameMode } from './model/gameMode'; import { MultipointIcon } from './model/multipointIcon'; import { PolygonIcon } from './model/polygonIcon'; import { PutCarArea } from './model/putCarArea'; import { Arrows } from './model/arrows'; import { Pipeline } from './model/pipeline'; import { PaintMode } from './model/paintModel'; import { WallSpace } from './model/wallSpace'; import { AxShape } from './model/axShape'; import { PropertyInfo } from './model/PropertyInfo'; @Component({ selector: 'app-working-area', templateUrl: './working-area.component.html', styleUrls: ['./working-area.component.scss'] }) /** * 工作区 */ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterViewInit { constructor(private eventManager: EventManager, public canvasData: CanvasShareDataService) { super(); } @ViewChild('content') content: ElementRef; /** * 父组件 */ @Input() init: any; /** * pixijs 程序 */ public app: PIXI.Application; /** * 资源加载器 */ public loader = PIXI.Loader.shared; /** * 背景图 */ public backgroundImage: PIXI.Sprite; /** * 预览单点图标 */ public previewSinglePointIcon = new PIXI.Sprite(); /** * 预览线段 */ public previewLineSegment = new PIXI.Graphics(); /** * 预览原点 */ public circleShadow = new PIXI.Graphics(); /** * 鼠标位置 */ public mousePosition: PIXI.Point = new PIXI.Point(0, 0); /** * 绘画模式 */ private paintMode: PaintMode; /** * 选择器 */ public selection: Selection = new Selection(this); /** * 当前鼠标的点 */ public currentClickPoint: PIXI.Graphics = new PIXI.Graphics(); /** * 绘制点集合 */ public paintPoints: PIXI.Point[]; /** * 绘制中的管线 */ public paintingPipeline: Pipeline; /** * 绘制中的箭头 */ public paintingArrows: Arrows = null; /** * 绘制中的多点图标 */ public paintingIcon: MultipointIcon; public paintingWall: AxShape; /** * 绘制中的连线 */ public paintingLine: PIXI.Graphics = new PIXI.Graphics(); /** * 绿色描边 */ public outlineFilterGreen = new OutlineFilter(2, 0x00ff00); /** * 拷贝素材数据 */ public copyData: any[] = []; /** * 确认绘制按钮 */ private enterPaintEndButton = PIXI.Sprite.from('assets/images/enterPaintButton.png'); /** * 框选工具图形 */ private rectToolGraphics = new PIXI.Graphics(); /** * 初始鼠标位置 */ private initialScreenMousePos: PIXI.Point = new PIXI.Point(); /** * 最终鼠标位置 */ private finalScreenMousePos: PIXI.Point = new PIXI.Point(); /** * 允许编辑 */ public allowEdit = true; /** * 动画控制器 */ public animator; public animation; public animationIcon; public animationTime; // 车辆作业面 public carAreas: PolygonIcon[]; // 车辆数据 public carData: Map = new Map(); // 当前选择的车辆id public selectCar: any = null; /** * 数据初始化 */ ngOnInit(): void { this.eventManager.addGlobalEventListener('window', 'keydown', (event: any) => { if (event.keyCode === 17) { this.selection.isMultiselection = true; } }); this.eventManager.addGlobalEventListener('window', 'keyup', (event: any) => { if (event.keyCode === 17) { this.selection.isMultiselection = false; this.rectToolGraphics.visible = false; this.rectToolGraphics.clear(); } // 按Del键删除选中的图标 if (event.keyCode === 46) { this.selection.objects.forEach(item => { delete this.canvasData.originaleveryStoreyData.data[item.assetData.Id]; this.backgroundImage.removeChild(this.backgroundImage.getChildByName(item.assetData.Id)); this.canvasData.isChange = true; }); this.emit('deleteIcon'); } }); // 打印当前工作区信息 this.eventManager.addGlobalEventListener('window', 'keypress', (event: any) => { // console.log(event.keyCode); if (event.keyCode === 32) { switch (this.paintMode) { case 0: console.log(`当前的绘制模式是:单点图标`); break; case 1: console.log(`当前的绘制模式是:线段图标`); break; case 2: console.log(`当前的绘制模式是:自定义多边形`); break; case 3: console.log(`当前的绘制模式是:水带多边形`); break; case 4: console.log(`当前的绘制模式是:暂无`); break; case 5: console.log(`当前的绘制模式是:暂无`); break; case 6: console.log(`当前的绘制模式是:结束绘制`); break; default: break; } console.log('当前楼层的数据:'); console.log(this.canvasData.originaleveryStoreyData.data); console.log('绘制中的管线:'); console.log(this.paintingPipeline); console.log('处置预案数据:'); console.log(this.canvasData.selectPanelPoint.Data); } }); } /** * 页面初始化 */ ngAfterViewInit(): void { this.createCanvas(); window.onresize = () => { this.resetCanvas(); }; } /** * * @param event 鼠标滑动事件 */ public mouseWheelHandel(event) { const delX = this.mousePosition.x - this.backgroundImage.position.x; const delY = this.mousePosition.y - this.backgroundImage.position.y; const pivot = this.backgroundImage.toLocal(this.mousePosition); const delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail))); if (delta > 0) { if (this.backgroundImage.scale.x >= 32) { this.backgroundImage.scale.x = 32; this.backgroundImage.scale.y = 32; this.emit('backgroundScale', this.backgroundImage.scale.x); return; } this.backgroundImage.pivot.set(pivot.x, pivot.y); this.backgroundImage.scale.x += this.backgroundImage.scale.x * 0.1; this.backgroundImage.scale.y += this.backgroundImage.scale.y * 0.1; this.backgroundImage.position.x += delX; this.backgroundImage.position.y += delY; } else if (delta < 0) { if (this.backgroundImage.scale.x <= 0.1) { this.backgroundImage.scale.x = 0.1; this.backgroundImage.scale.y = 0.1; this.emit('backgroundScale', this.backgroundImage.scale.x); return; } this.backgroundImage.pivot.set(pivot.x, pivot.y); this.backgroundImage.scale.x -= this.backgroundImage.scale.x * 0.1; this.backgroundImage.scale.y -= this.backgroundImage.scale.y * 0.1; this.backgroundImage.position.x += delX; this.backgroundImage.position.y += delY; } this.emit('backgroundScale', this.backgroundImage.scale.x); } /** * * @param icon 移动到选中车辆到屏幕中心点 */ public moveIconToScreenCenter(icon) { if (icon.parent === this.backgroundImage && ( icon.assetData.Type === 1 || icon.assetData.Type === 2 || icon.assetData.Type === 3 || icon.assetData.Type === 4 )) { console.log(this.backgroundImage.position); this.backgroundImage.pivot.set(icon.x, icon.y); this.backgroundImage.position.set(771, 404); clearTimeout(this.animationTime); this.animation?.pause(); this.animationIcon?.scale.set(1); this.animation = this.animator.breathe(icon, 10, 10, 30, true, 0); this.animationIcon = icon; this.animationTime = setTimeout(() => { this.animation?.pause(); this.animationIcon?.scale.set(1); }, 5000); } } /** * 创建画布 */ private createCanvas(): void { this.app = new PIXI.Application({ width: this.content.nativeElement.clientWidth, height: this.content.nativeElement.clientHeight, antialias: true, transparent: false, resolution: 1, backgroundColor: 0xE9FAFF }); this.content.nativeElement.appendChild(this.app.view); this.animator = new Charm(PIXI); this.app.ticker.add((delta) => { this.animator.update(); this.mousePosition = this.app.renderer.plugins.interaction.mouse.global; if (this.backgroundImage !== undefined) { this.previewSinglePointIcon.position = this.backgroundImage.toLocal(this.mousePosition); this.circleShadow.position = this.backgroundImage.toLocal(this.mousePosition); this.refreshPreviewLineSegment(this.currentClickPoint.position, this.circleShadow.position); } if (this.rectToolGraphics.visible === true) { const init = this.initialScreenMousePos; const final = this.finalScreenMousePos; this.rectToolGraphics.clear(); this.rectToolGraphics.lineStyle(2, 0x00ff00, 1); this.rectToolGraphics.beginFill(0xccccf2, 0.25); this.rectToolGraphics.drawRect(init.x, init.y, final.x - init.x, final.y - init.y); this.rectToolGraphics.endFill(); this.rectToolGraphics.closePath(); } if (this.paintingArrows !== null) { this.paintingArrows.assetData.pointB = new PIXI.Point(this.circleShadow.position.x, this.circleShadow.position.y); this.paintingArrows.refresh(); } }); /** * 选中事件 */ this.on('select', obj => { // this.moveIconToScreenCenter(obj); if (this.allowEdit) { if (obj instanceof MultipointIcon) { if (obj.assetData.GameMode === this.canvasData.gameMode) { obj.setPointVisiable(true); } else { obj.filters = [this.outlineFilterGreen]; } } else if (obj instanceof PolygonIcon) { if (obj.assetData.GameMode === this.canvasData.gameMode) { obj.setPointVisiable(true); } else { obj.filters = [this.outlineFilterGreen]; } } else { obj.filters = [this.outlineFilterGreen]; } } else { obj.filters = [this.outlineFilterGreen]; } }); /** * 取消选中事件 */ this.on('deselect', obj => { if (this.allowEdit) { if (obj instanceof MultipointIcon) { obj.setPointVisiable(false); } else if (obj instanceof PolygonIcon) { obj.setPointVisiable(false); } else { obj.filters = []; } } else { obj.filters = []; } }); this.on('backgroundScale', scale => { this.previewSinglePointIcon.scale.set((0.5 / scale)); this.backgroundImage.children.forEach(item => { if (item instanceof SinglePointIcon) { if (item.assetData.FixedSize) { const data = 1 / scale; item.scale.set(data); } else { const data = 1 / scale; item.text.scale.set(data); } } else if (item instanceof MultipointIcon) { const data = 1 / scale; item.text.scale.set(data); } else if (item instanceof PolygonIcon) { const data = 1 / scale; item.text.scale.set(data); } }); }); this.on('createIcon', obj => { if (obj.assetData.GameMode === GameMode.BasicInformation) { // if (obj.assetData.IsFromBuilding) { // this.canvasData.originalcompanyBuildingData.data[obj.assetData.Id] = obj.assetData; // } else { this.canvasData.originaleveryStoreyData.data[obj.assetData.Id] = obj.assetData; // } } else { // console.log(); if (this.canvasData.selectPanelPoint.Data === undefined || this.canvasData.selectPanelPoint.Data === null) { this.canvasData.selectPanelPoint.Data = new FloorNodeData(); } this.canvasData.selectPanelPoint.Data.Stock[obj.assetData.Id] = obj.assetData; } this.canvasData.isChange = true; }); } /** * 重置画布 */ public resetCanvas() { this.app.renderer.resize(this.content.nativeElement.clientWidth, this.content.nativeElement.clientHeight); } /** * 设置名称显示 * @param value true 显示 false 隐藏 * @param mode BasicInformation = 0 基本信息 Assignment想定作业 = 1 想定作业 */ public setNameVisible(value: boolean, mode: GameMode): void { this.backgroundImage?.children.forEach(item => { if (item instanceof SinglePointIcon) { item.setNameVisible(value, mode); } else if (item instanceof MultipointIcon) { item.setNameVisible(value, mode); } else if (item instanceof PolygonIcon) { item.setNameVisible(value, mode); } }); } /** * 根据id刷新图标 * @param id 图标数据id */ public refreshIcon(id: string): void { const icon = this.backgroundImage.children.find(item => item.name === id); if (icon instanceof SinglePointIcon) { icon.refresh(); } else if (icon instanceof MultipointIcon) { icon.refresh(); } else if (icon instanceof PolygonIcon) { icon.refresh(); } } /** * * @param value 缩放倍数 */ public setIconScale(value: number): void { this.backgroundImage.children.forEach(item => { if (item instanceof SinglePointIcon) { item.scale.set(value); } else if (item instanceof MultipointIcon) { } else if (item instanceof PolygonIcon) { } }); } /** * 设置高亮 */ public setHighlight(ids: string[]): void { this.selection.deselectAll(); ids.forEach(item => { let obj = this.backgroundImage.getChildByName(item); if (obj === null) { obj = this.app.stage.getChildByName(item); } this.selection.select(obj); }); } /** * 刷新工作区 */ public async refresh() { this.setPaintMode(PaintMode.endPaint); this.resetCanvas(); this.destroyBackgroundImage(); await this.createBackgroundImage(this.canvasData.selectStorey.imageUrl); // this.refreshBackgroundImage(); // this.versionChecking(); const floorData = this.canvasData.originaleveryStoreyData.data; // const buildingData = this.canvasData.originalcompanyBuildingData.data; // const floor = this.canvasData.selectStorey; // // key=>属性名 data[key]=>属性值 Object.keys(floorData).forEach((key) => { // console.log(floorData[key]); switch (floorData[key].InteractiveMode) { case 0: const singleIcon = new SinglePointIcon(floorData[key], this); break; case 1: const icon = new MultipointIcon(floorData[key], this); break; case 2: const polygonIcon = new PolygonIcon(floorData[key], this); break; } }); // Object.keys(buildingData).forEach((key) => { // if (buildingData[key].FloorId === floor.id) { // switch (buildingData[key].InteractiveMode) { // case 0: // const singleIcon = new SinglePointIcon(buildingData[key], this); // break; // case 1: // const icon = new MultipointIcon(buildingData[key], this); // break; // case 2: // const polygonIcon = new PolygonIcon(buildingData[key], this); // break; // } // } // }); // 加载处置节点数据 const nodeData = this.canvasData.selectPanelPoint.Data; if (nodeData !== undefined && nodeData !== null) { Object.keys(nodeData).forEach((key) => { Object.keys(nodeData[key]).forEach((tempKey) => { switch (nodeData[key][tempKey].InteractiveMode) { case 0: const singleIcon = new SinglePointIcon(nodeData[key][tempKey], this); break; case 1: if (nodeData[key][tempKey].Name === '水带') { const pipeline = new Pipeline(nodeData[key][tempKey], this); } else { const icon = new MultipointIcon(nodeData[key][tempKey], this); } break; case 2: const polygonIcon = new PolygonIcon(nodeData[key][tempKey], this); break; } }); }); } this.emit('backgroundScale', this.backgroundImage.scale.x); } /** * * @param id 图标ID * @param b 显示/隐藏 */ public setIconVisible(ids: string[], b: boolean) { ids.forEach(item => { this.backgroundImage.getChildByName(item).visible = b; }); } // /** // * 版本检查 // */ // public versionChecking(): void { // const floorData = this.canvasData.originaleveryStoreyData; // const buildingData = this.canvasData.originalcompanyBuildingData; // const nodeData = this.canvasData.selectPanelPoint; // if (floorData.version && floorData.version === '1.0') { // floorData.version = '2.0'; // Object.keys(floorData.data).forEach(item => { // floorData.data[item].Point.y *= -1; // floorData.data[item].MultiPoint?.forEach(element => { // element.y *= -1; // }); // }); // } // if (buildingData.version && buildingData.version === '1.0') { // buildingData.version = '2.0'; // Object.keys(buildingData.data).forEach(item => { // buildingData.data[item].Point.y *= -1; // buildingData.data[item].MultiPoint?.forEach(element => { // element.y *= -1; // }); // }); // } // if (nodeData.Version && nodeData.Version === '1.0') { // nodeData.Version = '2.0'; // console.log(this.canvasData.selectPanelPoint.Version); // Object.keys(nodeData.Data).forEach((key) => { // Object.keys(nodeData.Data[key]).forEach((tempKey) => { // nodeData.Data[key][tempKey].Point.y *= -1; // nodeData.Data[key][tempKey].MultiPoint?.forEach(element => { // element.y *= -1; // }); // }); // }); // } // } /** * 创建确认绘制结束按钮 */ private createEnterPaintEndButton() { this.enterPaintEndButton.width = 60; this.enterPaintEndButton.height = 60; this.enterPaintEndButton.anchor.set(0.5); this.enterPaintEndButton.position = new PIXI.Point(0, 0); this.enterPaintEndButton.interactive = true; this.enterPaintEndButton.buttonMode = true; this.enterPaintEndButton .on('mousedown', event => { event.stopPropagation(); this.enterPaint(); }); this.backgroundImage.addChild(this.enterPaintEndButton); this.enterPaintEndButton.zIndex = this.backgroundImage.children.length; this.enterPaintEndButton.visible = false; } /** * 创建背景图 */ private async createBackgroundImage(imageUrl: string): Promise { const image = await PIXI.Texture.fromURL(imageUrl); this.backgroundImage = new PIXI.Sprite(image); this.backgroundImage.anchor.set(0.5); this.backgroundImage.x = this.app.view.width / 2; this.backgroundImage.y = this.app.view.height / 2; this.backgroundImage.interactive = true; this.backgroundImage.name = 'background'; // const left = this.init.element.nativeElement.querySelector('.functionalDomainLeft').clientWidth; // const right = this.init.element.nativeElement.querySelector('.functionalDomainRight').clientWidth; const imageWidth = this.backgroundImage.texture.width; const imageHeight = this.backgroundImage.texture.height; const appWidth = this.app.view.width - 470; const appHeight = this.app.view.height; const wScale = appWidth / imageWidth; const hScale = appHeight / imageHeight; const scale = wScale < hScale ? wScale : hScale; this.backgroundImage.scale.set(scale); this.backgroundImage.sortableChildren = true; this.backgroundImage .on('mousedown', event => { if (!event.currentTarget.dragging && this.selection.isMultiselection === false) { event.currentTarget.data = event.data; event.currentTarget.dragging = true; event.currentTarget.dragPoint = event.data.getLocalPosition(event.currentTarget.parent); event.currentTarget.dragPoint.x -= event.currentTarget.x; event.currentTarget.dragPoint.y -= event.currentTarget.y; switch (this.paintMode) { case PaintMode.endPaint: console.log(this.backgroundImage.toLocal(this.mousePosition)); break; case PaintMode.singlePointIcon: const json = JSON.parse(JSON.stringify(this.canvasData.selectTemplateData.propertyInfos)); const list = []; json.forEach(element => { const property = new PropertyInfo(element); list.push(property); }); const assetData = { TemplateId: this.canvasData.selectTemplateData.id, CanConnect: this.canvasData.selectTemplateData.canConnect, Pipelines: new Array(), FloorId: this.canvasData.selectStorey.id, Angle: this.canvasData.selectTemplateData.angle, Color: this.canvasData.selectTemplateData.color, Enabled: this.canvasData.selectTemplateData.enabled, FillMode: this.canvasData.selectTemplateData.fillMode, FireElementId: this.canvasData.selectTemplateData.fireElementId, FixedSize: this.canvasData.selectTemplateData.fixedSize, Height : 32, Width : 32, Id: ObjectID.default.generate(), ImageUrl: this.canvasData.selectTemplateData.imageUrl, InteractiveMode: this.canvasData.selectTemplateData.interactiveMode, MultiPoint : null, Point: new PIXI.Point(this.previewSinglePointIcon.x, this.previewSinglePointIcon.y), Name : this.canvasData.selectTemplateData.name, PropertyInfos: list, Border : this.canvasData.selectTemplateData.border, DrawMode : this.canvasData.selectTemplateData.drawMode, Thickness : this.canvasData.selectTemplateData.thickness, IsFromBuilding : this.canvasData.selectTemplateData.isFromBuilding, GameMode : this.canvasData.gameMode }; const singleIcon = new SinglePointIcon(assetData, this); this.emit('createIcon', singleIcon); this.emit('backgroundScale', this.backgroundImage.scale.x); break; case PaintMode.lineIcon: this.previewLineSegment.visible = true; this.currentClickPoint.position = new PIXI.Point(this.circleShadow.x, this.circleShadow.y); this.paintPoints.push(new PIXI.Point(this.circleShadow.x, this.circleShadow.y)); if (this.paintPoints.length >= 2) { this.enterPaintEndButton.position = this.circleShadow.position; this.enterPaintEndButton.visible = true; } if (this.paintingIcon !== null) { this.backgroundImage.removeChild(this.paintingIcon); } const jsonObject = JSON.parse(JSON.stringify(this.canvasData.selectTemplateData.propertyInfos)); const propertyList = []; jsonObject.forEach(element => { const property = new PropertyInfo(element); propertyList.push(property); }); const assetData1 = { TemplateId: this.canvasData.selectTemplateData.id, FloorId: this.canvasData.selectStorey.id, Angle: this.canvasData.selectTemplateData.angle, Color: this.canvasData.selectTemplateData.color, Enabled: this.canvasData.selectTemplateData.enabled, FillMode: this.canvasData.selectTemplateData.fillMode, FireElementId: this.canvasData.selectTemplateData.fireElementId, FixedSize: this.canvasData.selectTemplateData.fixedSize, Height: 32, Width: 32, Id: ObjectID.default.generate(), ImageUrl: this.canvasData.selectTemplateData.imageUrl, InteractiveMode: this.canvasData.selectTemplateData.interactiveMode, MultiPoint: JSON.parse(JSON.stringify(this.paintPoints)), Point: new PIXI.Point(0, 0), Name: this.canvasData.selectTemplateData.name, PropertyInfos: propertyList, Border: this.canvasData.selectTemplateData.border, DrawMode: this.canvasData.selectTemplateData.drawMode, Thickness: this.canvasData.selectTemplateData.thickness, IsFromBuilding: this.canvasData.selectTemplateData.isFromBuilding, GameMode: this.canvasData.gameMode }; // const assetData1 = { // ImageUrl: this.canvasData.selectTemplateData.imageUrl, // Point: new PIXI.Point(0, 0), // Width: 32, // Height: 32, // MultiPoint: this.paintPoints, // Name: this.canvasData.selectTemplateData.name // }; this.paintingIcon = new MultipointIcon(assetData1, this); // this.paintingIcon = new MultipointIcon(this.previewSinglePointIcon.texture, new PIXI.Point(0, 0), this.paintPoints, this, // this.canvasData.selectTemplateData.name); this.emit('backgroundScale', this.backgroundImage.scale.x); break; case PaintMode.polygonIcon: this.previewLineSegment.visible = true; this.currentClickPoint.position = new PIXI.Point(this.circleShadow.x, this.circleShadow.y); this.paintPoints.push(new PIXI.Point(this.circleShadow.x, this.circleShadow.y)); if (this.paintPoints.length === 1) { this.enterPaintEndButton.position = this.circleShadow.position; } else if (this.paintPoints.length >= 3) { this.enterPaintEndButton.visible = true; } this.paintPoints.forEach((value, index, array) => { if (index === 0) { this.paintingLine.clear(); this.paintingLine.lineStyle(1, 0xffd900, 1); this.paintingLine.moveTo(value.x, value.y); } else { this.paintingLine.lineTo(value.x, value.y); } }); // if (this.paintingIcon !== null) { // this.backgroundImage.removeChild(this.paintingIcon); // } // this.paintingIcon = new PolygonIcon(this.paintPoints, this); break; case PaintMode.Pipeline: if (this.paintingPipeline !== null) { this.currentClickPoint.position = new PIXI.Point(this.circleShadow.x, this.circleShadow.y); this.paintPoints.push(new PIXI.Point(this.circleShadow.x, this.circleShadow.y)); this.paintingPipeline.assetData.MultiPoint = JSON.parse(JSON.stringify(this.paintPoints)); this.paintingPipeline.refresh(); } // this.emit('backgroundScale', this.backgroundImage.scale.x); break; case PaintMode.Arrows: if (this.paintingArrows === null) { const data = { Id: ObjectID.default.generate(), name: 'string', point: new PIXI.Point(this.circleShadow.x, this.circleShadow.y), pointA: new PIXI.Point(this.circleShadow.x, this.circleShadow.y), pointB: new PIXI.Point(this.circleShadow.x, this.circleShadow.y), source: 'assets/images/进攻方向.png', }; this.paintingArrows = new Arrows(data, this); } else { this.paintingArrows.ready = true; this.paintingArrows = null; this.paintMode = PaintMode.endPaint; } break; case PaintMode.Car: // this.previewLineSegment.visible = true; // this.currentClickPoint.position = new PIXI.Point(this.circleShadow.x, this.circleShadow.y); // this.paintPoints.push(new PIXI.Point(this.circleShadow.x, this.circleShadow.y)); // if (this.paintPoints.length >= 2) { // this.enterPaintEndButton.position = this.circleShadow.position; // this.enterPaintEndButton.visible = true; // } // if (this.paintingWall !== null) { // this.backgroundImage.removeChild(this.paintingWall); // } // const jsonObject1 = JSON.parse(JSON.stringify(this.canvasData.selectTemplateData.propertyInfos)); // const propertyList1 = []; // jsonObject1.forEach(element => { // const property = new PropertyInfo(element); // propertyList1.push(property); // }); // const assetData11 = { // TemplateId: this.canvasData.selectTemplateData.id, // FloorId: this.canvasData.selectStorey.id, // Angle: this.canvasData.selectTemplateData.angle, // Color: this.canvasData.selectTemplateData.color, // Enabled: this.canvasData.selectTemplateData.enabled, // FillMode: this.canvasData.selectTemplateData.fillMode, // FireElementId: this.canvasData.selectTemplateData.fireElementId, // FixedSize: this.canvasData.selectTemplateData.fixedSize, // Height: 32, // Width: 32, // Id: ObjectID.default.generate(), // ImageUrl: this.canvasData.selectTemplateData.imageUrl, // InteractiveMode: this.canvasData.selectTemplateData.interactiveMode, // MultiPoint: JSON.parse(JSON.stringify(this.paintPoints)), // Point: new PIXI.Point(0, 0), // Name: this.canvasData.selectTemplateData.name, // PropertyInfos: propertyList1, // Border: this.canvasData.selectTemplateData.border, // DrawMode: this.canvasData.selectTemplateData.drawMode, // Thickness: this.canvasData.selectTemplateData.thickness, // IsFromBuilding: this.canvasData.selectTemplateData.isFromBuilding, // GameMode: this.canvasData.gameMode // }; // this.paintingWall = new WallSpace(assetData11, this); // this.emit('backgroundScale', this.backgroundImage.scale.x); break; } } else if (!event.currentTarget.dragging && this.selection.isMultiselection === true) { this.rectToolGraphics.visible = true; event.currentTarget.dragging = true; this.initialScreenMousePos = this.backgroundImage.toLocal(this.mousePosition); this.finalScreenMousePos = this.backgroundImage.toLocal(this.mousePosition); } }) .on('mouseup', event => { if (event.currentTarget.dragging) { event.currentTarget.dragging = false; event.currentTarget.data = null; } if (this.rectToolGraphics.visible === true) { this.backgroundImage.children.forEach(item => { if (item instanceof SinglePointIcon || item instanceof MultipointIcon || item instanceof PolygonIcon) { if (this.rectToolGraphics.getLocalBounds().contains(item.x, item.y)) { this.selection.select(item); } } }); this.rectToolGraphics.clear(); this.rectToolGraphics.visible = false; } }) .on('mouseupoutside', event => { if (event.currentTarget.dragging) { event.currentTarget.dragging = false; event.currentTarget.data = null; } }) .on('mousemove', event => { if (event.currentTarget.dragging && this.selection.isMultiselection === false) { const newPosition = event.currentTarget.data.getLocalPosition(event.currentTarget.parent); event.currentTarget.x = newPosition.x - event.currentTarget.dragPoint.x; event.currentTarget.y = newPosition.y - event.currentTarget.dragPoint.y; } else if (event.currentTarget.dragging && this.selection.isMultiselection === true) { if (this.rectToolGraphics.visible === true) { this.finalScreenMousePos = this.backgroundImage.toLocal(this.mousePosition); } } }) .on('rightclick', event => { event.stopPropagation(); this.selection.deselectAll(); this.setPaintMode(PaintMode.endPaint); }) .on('pointerover', (event) => { this.previewSinglePointIcon.filters = null; }) .on('pointerout', (event) => { this.previewSinglePointIcon.filters = null; }); this.app.stage.addChild(this.backgroundImage); this.createPreviewSinglePointIcon(); this.createPreviewLineSegment(); this.createCircleShadow(); this.createEnterPaintEndButton(); this.backgroundImage.addChild(this.paintingLine); } /** * 刷新背景图 */ public refreshBackgroundImage(): void { if (!this.canvasData.selectStorey.imageUrl) { this.backgroundImage.visible = false; } else { this.backgroundImage.texture = PIXI.Texture.from(this.canvasData.selectStorey.imageUrl); this.backgroundImage.angle = this.canvasData.selectStorey.imageAngle; this.backgroundImage.visible = true; } } /** * 清空画布 */ public destroyBackgroundImage(): void { this.app.stage.removeChild(this.backgroundImage); } /** * 设置背景图缩放 * @param scale 缩放系数 */ public setBackgroundScale(scale: number): void { this.backgroundImage.scale.set(scale); this.emit('backgroundScale', this.backgroundImage.scale.x); } /** * 设置背景图角度 * @param imageAngle 角度值 */ public setBackgroundAngle(imageAngle: number) { this.backgroundImage.angle = imageAngle; } /** * 创建预览单点图标 */ private createPreviewSinglePointIcon(): void { this.previewSinglePointIcon = PIXI.Sprite.from('assets/images/noImg.png'); this.previewSinglePointIcon.width = 32; this.previewSinglePointIcon.height = 32; this.previewSinglePointIcon.alpha = 1; this.previewSinglePointIcon.anchor.set(0.5); this.previewSinglePointIcon.visible = false; this.backgroundImage.addChild(this.previewSinglePointIcon); } /** * 改变预览单点图标 * @param uri 图片地址 */ private changePreviewSinglePointIcon(uri: string): void { this.previewSinglePointIcon.texture = PIXI.Texture.from(uri); this.previewSinglePointIcon.visible = true; } /** * 创建预览线段 */ private createPreviewLineSegment() { this.previewLineSegment.visible = false; this.backgroundImage.addChild(this.currentClickPoint); this.backgroundImage.addChild(this.previewLineSegment); this.backgroundImage.addChild(this.rectToolGraphics); this.rectToolGraphics.visible = false; } /** * 刷新预览线段 * @param pointA 点A * @param pointB 点B */ private refreshPreviewLineSegment(pointA: PIXI.Point, pointB: PIXI.Point) { this.previewLineSegment.clear(); this.previewLineSegment.lineStyle(1, 0xffd900, 1); this.previewLineSegment.moveTo(pointA.x, pointA.y); this.previewLineSegment.lineTo(pointB.x, pointB.y ); } /** * 创建半径图标影子 * @param x 半径 */ private createCircleShadow(): void { this.circleShadow.beginFill(0xFFCC5A); this.circleShadow.drawCircle(0, 0, 10); this.circleShadow.endFill(); this.circleShadow.visible = false; this.backgroundImage.addChild(this.circleShadow); } showConnectionPoint(b: boolean) { this.backgroundImage?.children.forEach(item => { if (item instanceof SinglePointIcon) { if (item.assetData.CanConnect) { item.showConnectionPoint(b); } } }); } /** * 开始绘制 */ public beginPaint() { if (this.canvasData.selectTemplateData.name === '水带') { this.showConnectionPoint(true); this.setPaintMode(PaintMode.Pipeline); return; } switch (this.canvasData.selectTemplateData.interactiveMode) { case 0: this.setPaintMode(PaintMode.singlePointIcon); break; case 1: this.setPaintMode(PaintMode.lineIcon); break; case 2: this.setPaintMode(PaintMode.polygonIcon); break; case 3: if (this.canvasData.selectTemplateData.name) { this.setPaintMode(PaintMode.Pipeline); } break; } } /** * 初始化管线数据 */ public initPipelineData(): void { this.paintPoints = []; this.paintingPipeline = null; } public beginPaintingArrows(): void { this.paintMode = PaintMode.Arrows; } /** * 设置绘制状态 * @param mode 状态 */ public setPaintMode(mode: PaintMode) { if (this.paintMode === mode) { return; } this.paintMode = mode; if (this.paintMode !== PaintMode.Pipeline) { this.showConnectionPoint(false); } switch (this.paintMode) { case PaintMode.Pipeline: break; case PaintMode.singlePointIcon: this.previewSinglePointIcon.visible = false; this.changePreviewSinglePointIcon(this.canvasData.selectTemplateData.imageUrl); break; case PaintMode.lineIcon: this.circleShadow.visible = false; this.previewLineSegment.visible = false; this.paintPoints.splice(0, this.paintPoints.length); if (this.paintingIcon !== null) { this.backgroundImage.removeChild(this.paintingIcon); } this.previewSinglePointIcon.texture = PIXI.Texture.from(this.canvasData.selectTemplateData.imageUrl); this.circleShadow.visible = true; break; case PaintMode.polygonIcon: this.circleShadow.visible = false; this.previewLineSegment.visible = false; this.paintingIcon = null; this.paintPoints.splice(0, this.paintPoints.length); this.paintingLine.clear(); this.circleShadow.visible = true; break; case PaintMode.endPaint: // 重置组件状态 if ( this.paintingIcon !== undefined && this.paintingIcon !== null) { this.backgroundImage.removeChild(this.paintingIcon); } if (this.paintingPipeline !== undefined && this.paintingPipeline !== null) { this.backgroundImage.removeChild(this.paintingPipeline); } this.paintingLine.clear(); this.resetData(); break; default: break; } } /** * 获取绘制状态 */ public getPaintMode(): PaintMode { return this.paintMode; } /** * 重置 */ public resetData() { this.previewSinglePointIcon.filters = null; this.previewSinglePointIcon.visible = false; this.previewSinglePointIcon.angle = 0; this.initPipelineData(); // this.circleShadow.visible = false; this.previewLineSegment.visible = false; } /** * 确认绘制 */ private enterPaint(): void { this.previewLineSegment.visible = false; this.enterPaintEndButton.visible = false; switch (this.paintMode) { case PaintMode.lineIcon: if (this.paintPoints.length >= 2) { this.emit('createIcon', this.paintingIcon); this.paintingIcon = null; } break; case PaintMode.polygonIcon: this.paintingLine.clear(); if (this.paintPoints.length >= 3) { const jsonList = JSON.parse(JSON.stringify(this.canvasData.selectTemplateData.propertyInfos)); const propertyList = []; jsonList.forEach(element => { const property = new PropertyInfo(element); propertyList.push(property); }); const assetData = { TemplateId: this.canvasData.selectTemplateData.id, FloorId: this.canvasData.selectStorey.id, Angle: this.canvasData.selectTemplateData.angle, Color: this.canvasData.selectTemplateData.color, Enabled: this.canvasData.selectTemplateData.enabled, FillMode: this.canvasData.selectTemplateData.fillMode, FireElementId: this.canvasData.selectTemplateData.fireElementId, FixedSize: this.canvasData.selectTemplateData.fixedSize, Height: 32, Width: 32, Id: ObjectID.default.generate(), ImageUrl: this.canvasData.selectTemplateData.imageUrl, InteractiveMode: this.canvasData.selectTemplateData.interactiveMode, MultiPoint: JSON.parse(JSON.stringify(this.paintPoints)), Point: new PIXI.Point(0, 0), Name: this.canvasData.selectTemplateData.name, PropertyInfos: propertyList, Border: this.canvasData.selectTemplateData.border, DrawMode: this.canvasData.selectTemplateData.drawMode, Thickness: this.canvasData.selectTemplateData.thickness, IsFromBuilding: this.canvasData.selectTemplateData.isFromBuilding, GameMode: this.canvasData.gameMode }; const polygonIcon = new PolygonIcon(assetData, this); this.emit('createIcon', polygonIcon); } break; } this.paintPoints.splice(0, this.paintPoints.length); this.emit('backgroundScale', this.backgroundImage.scale.x); } /** * 复制 */ public copy(): void { this.copyData = []; this.selection.objects.forEach(item => { const newData = JSON.parse(JSON.stringify(item.assetData)); this.copyData.push(newData); }); } /** * 粘贴 */ public paste(companyId: string, buildingId: string, floorId: string): void { this.copyData.forEach(item => { item.Point = new PIXI.Point(item.Point.x + 5, item.Point.y + 5); const newData = JSON.parse(JSON.stringify(item)); newData.Id = ObjectID.default.generate(), newData.CompanyId = companyId; newData.BuildingId = buildingId; newData.FloorId = floorId; newData.Point = new PIXI.Point(item.Point.x + 5, item.Point.y + 5); // if (newData.IsFromBuilding) { // this.canvasData.originalcompanyBuildingData.data[newData.Id] = newData; // } else { this.canvasData.originaleveryStoreyData.data[newData.Id] = newData; // } switch (item.InteractiveMode) { case PaintMode.singlePointIcon: const singleIcon = new SinglePointIcon(newData, this); break; case PaintMode.lineIcon: const lineIcon = new MultipointIcon(newData, this); break; case PaintMode.polygonIcon: const polygonIcon = new PolygonIcon(newData, this); break; } this.selection.select(this.backgroundImage.getChildByName(newData.Id)); }); } } /** * 选择器 */ export class Selection { constructor(private workingArea: WorkingAreaComponent) {} public objects: any[] = []; public isMultiselection = false; /** * 返回选择器中是否包含对象 * @param obj 对象 */ public contains(obj: any): boolean { return this.objects.includes(obj); } /** * 选定对象 * @param obj 对象 */ public select(obj: any) { if (!this.contains(obj)) { this.workingArea.emit('select', obj); this.objects.push(obj); } } /** * 取消选定对象 * @param obj 对象 */ public deselect(obj: any) { if (this.contains(obj)) { this.workingArea.emit('deselect', obj); const idx = this.objects.findIndex(x => x === obj); this.objects.splice(idx, 1); } } /** * 选定或取消选定对象 * @param obj 对象 */ public selectOrDeselect(obj: any) { if (this.contains(obj)) { this.deselect(obj); } else { this.select(obj); } } /** * 取消选定所有已选定对象 */ public deselectAll() { this.objects.forEach(item => { this.workingArea.emit('deselect', item); }); this.objects.splice(0, this.objects.length); } /** * 取消选定所有对象后选定一个对象 * @param obj 对象 */ public selectOne(obj: any) { if (this.isMultiselection) { this.selectOrDeselect(obj); } else { this.deselectAll(); this.select(obj); } } /** * 选定对象集合中所有对象 * @param objects 对象集合 */ public selectAll(objects: any[]) { this.objects.forEach(item => { this.select(item); }); } } /** * 车辆类型 */ export enum Type { 水源 = 0, 举高喷射消防车 = 1, 泡沫消防车 = 2, 水罐消防车 = 3, 压缩空气泡沫消防车 = 4 }