Browse Source

[更新] 采集工具更新

develop
徐振升 4 years ago
parent
commit
e140f8ec7b
  1. 1
      debug.log
  2. 71
      package-lock.json
  3. 402
      src/app/canvas-share-data.service.ts
  4. 2
      src/app/ui/collection-tools/collection-tools.component.ts
  5. 836
      src/app/working-area/charm.js
  6. 62
      src/app/working-area/model/PropertyInfo.ts
  7. 41
      src/app/working-area/model/arrows.ts
  8. 322
      src/app/working-area/model/axArrowConnector.ts
  9. 443
      src/app/working-area/model/axImageShape.ts
  10. 27
      src/app/working-area/model/axPreviewImageShape.ts
  11. 76
      src/app/working-area/model/axShape.ts
  12. 7
      src/app/working-area/model/gameMode.ts
  13. 246
      src/app/working-area/model/multipointIcon.ts
  14. 33
      src/app/working-area/model/paintModel.ts
  15. 328
      src/app/working-area/model/pipeline.ts
  16. 269
      src/app/working-area/model/polygonIcon.ts
  17. 59
      src/app/working-area/model/putCarArea.ts
  18. 1400
      src/app/working-area/working-area.component.ts
  19. BIN
      src/assets/images/enterPaintButton.jpg
  20. BIN
      src/assets/images/enterPaintButton.png
  21. BIN
      src/assets/images/testBackground.jpg

1
debug.log

@ -0,0 +1 @@
[1214/094922.722:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)

71
package-lock.json generated

@ -10508,7 +10508,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -10529,12 +10530,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -10549,17 +10552,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -10676,7 +10682,8 @@
"inherits": { "inherits": {
"version": "2.0.4", "version": "2.0.4",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -10688,6 +10695,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -10702,6 +10710,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -10709,12 +10718,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.9.0", "version": "2.9.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -10733,6 +10744,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -10822,7 +10834,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -10834,6 +10847,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -10919,7 +10933,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -10955,6 +10970,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -10974,6 +10990,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -11017,12 +11034,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.1.1", "version": "3.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
@ -17551,7 +17570,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -17594,7 +17614,8 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
@ -17605,7 +17626,8 @@
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -17722,7 +17744,8 @@
"inherits": { "inherits": {
"version": "2.0.4", "version": "2.0.4",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -17734,6 +17757,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -17763,6 +17787,7 @@
"version": "2.9.0", "version": "2.9.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -17781,6 +17806,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -17870,7 +17896,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -17882,6 +17909,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -17967,7 +17995,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -18003,6 +18032,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -18022,6 +18052,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -18065,12 +18096,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.1.1", "version": "3.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },

402
src/app/canvas-share-data.service.ts

@ -1,19 +1,35 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import {ReplaySubject} from 'rxjs';
import { Observable } from 'rxjs';
import { GameMode } from './working-area/model/gameMode';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class CanvasShareDataService { export class CanvasShareDataService {
constructor() { } constructor() { }
private _sendMessage: ReplaySubject<any> = new ReplaySubject<any>(1);
GameMode: any;
isChange = false; // 数据 是否改动 isChange = false; // 数据 是否改动
selectStorey: any = {area: '', details: ''}; // 选择当前 楼层 数据
selectTemplateData: any; // 选择当前 模板数据 selectTemplateData: any; // 选择当前 模板数据
// 总平面图/建筑 楼层
selectStorey: any = {area: '', details: ''}; // 选择当前 楼层 数据
originalcompanyBuildingData: any; // 单位/建筑 数据 originalcompanyBuildingData: any; // 单位/建筑 数据
originaleveryStoreyData: any; // 总平面图/楼层/区域 楼层数据 originaleveryStoreyData: any; // 总平面图/楼层/区域 楼层数据
// 总平面图/建筑 楼层
// 处置 节点
allDisposalNode: any = []; // 所有 处置节点
allNodeMarkers: any; // 灾情 标签信息
selectPanelPoint: DisposalNodeData = new DisposalNodeData();
selectPanelPointBaseData: any = {description: '', notes: '', weather: '', airTemperature: '', windDirection: '', windScale: ''}; // 当前 数据节点 所对应的 天气,详情 数据节点
// 处置 节点
/**
*
*/
gameMode: GameMode = GameMode.BasicInformation;
facilityAssetsName = new Map<string, string>([ facilityAssetsName = new Map<string, string>([
[ '消防水池', '消防水池'], [ '消防水池', '消防水池'],
@ -46,6 +62,26 @@ export class CanvasShareDataService {
[ '消防管网', '消防管网'], [ '消防管网', '消防管网'],
[ 'DCS控制室', 'DCS控制室'] [ 'DCS控制室', 'DCS控制室']
]); ]);
/** * *
* @param message * @returns {Observavle<any>} */
public sendMessage(message: any) {
this._sendMessage.next(message);
}
public getMessage(): Observable <any> {
return this._sendMessage.asObservable();
}
// 处置节点 筛选出 匹配数据 匹配不到 return undefined
findDisposalNode(parentId: string= null, name: string= null) {
if (parentId && name) { // 匹配 父id, name
const returnData = this.allDisposalNode.find(item => item.parentId === parentId && item.name === name);
return returnData;
} else { // 匹配 id
const returnData = this.allDisposalNode.find(item => item.id === parentId);
return returnData;
}
}
/** /**
* *
*/ */
@ -208,6 +244,31 @@ export class CanvasShareDataService {
}); });
return list; return list;
} }
/**
*
* @param json
*/
public deserialize<T>(json: any): T {
const obj: T = JSON.parse(
json,
(_, val) => {
if (val === null) { return null; }
if (Array.isArray(val) || typeof val !== 'object') {
return val;
}
return Object.entries(val).reduce((a, [key, val]) => {
const count = key.length;
if (count > 1) {
a[key[0].toUpperCase() + key.substring(1, count)] = val;
} else {
a[key] = val;
}
return a;
}, {});
}
);
return obj;
}
} }
/** /**
@ -334,3 +395,338 @@ export enum PropertyType {
// 供给类型 // 供给类型
SupplyType SupplyType
} }
/**
*
*/
export class DisposalNode {
/**
*
*/
public Id: string;
/**
*
*/
public Name: string;
/**
*
*/
public Level: number;
/**
*
*/
public Order: number;
/**
*
*/
public Description: string;
/**
*
*/
public Notes: string;
/**
*
*/
public Weather: string;
/**
*
*/
public AirTemperature?: number;
/**
*
*/
public WindDirection: Direction;
/**
*
*/
public WindScale: WindScale;
/**
*
*/
public ImageNames: string[];
/**
*
*/
public ImageUrls: string[];
/**
*
*/
public ParentId: string;
/**
*
*/
public DisasterId: string;
/**
*
*/
public PlanComponentId: string;
/**
*
*/
public CompanyId: string;
/**
*
*/
public SitePlanId: string;
/**
*
*/
public BuildingId: string;
/**
*
*/
public BuildingAreaId: string;
}
/**
*
*/
export enum Direction {
/**
*
*/
East,
/**
* 西
*/
West,
/**
*
*/
South,
/**
*
*/
North,
/**
*
*/
Southeast,
/**
* 西
*/
Southwest,
/**
*
*/
Northeast,
/**
* 西
*/
Northwest
}
/**
*
*/
export enum WindScale {
WS0,
WS1,
WS2,
WS3,
WS4,
WS5,
WS6,
WS7,
WS8,
WS9,
WS10,
WS11,
WS12,
WS13,
WS14,
WS15,
WS16,
WS17,
WS18
}
/**
*
*/
export class DisposalNodeData {
/**
*
*/
public Id: string;
/**
*
*/
public Data: any;
/**
*
*/
public Version: string;
/**
*
*/
public DisposalNodeId: string;
/**
*
*/
public PlanComponentId: string;
}
/**
*
*/
export class FloorNodeData {
/**
*
*/
public Stock: Map<string, AssetData> = new Map<string, AssetData>();
/**
*
*/
public Increment: Map<string, AssetData> = new Map<string, AssetData>();
/**
*
*/
public DefinedIncrement: Map<string, AssetData> = new Map<string, AssetData>();
}
/**
*
*/
export class AssetData {
/// <summary>
/// 模板编号
/// </summary>
public TemplateId: string;
/// <summary>
/// 编号
/// </summary>
public Id: string;
/// <summary>
/// 名称
/// </summary>
public Name: string;
/// <summary>
/// 角度
/// </summary>
public Angle: number;
/// <summary>
/// 颜色
/// </summary>
public Color: string;
/// <summary>
/// 坐标
/// </summary>
public Point: PIXI.Point;
/// <summary>
/// 宽度
/// </summary>
public Width: number;
/// <summary>
/// 高度
/// </summary>
public Height: number;
/// <summary>
/// 是否启用
/// </summary>
public Enabled: boolean;
/// <summary>
/// 填充方式
/// </summary>
public FillMode: FillMode;
/// <summary>
/// 图片地址
/// </summary>
public ImageUrl: string;
/// <summary>
/// 是否固定大小
/// </summary>
public FixedSize: boolean;
/// <summary>
/// 点路径
/// </summary>
public MultiPoint: PIXI.Point[];
/// <summary>
/// 建筑ID
/// </summary>
public BuildingId: string;
/// <summary>
/// 单位ID
/// </summary>
public CompanyId: string;
/// <summary>
/// 楼层编号
/// </summary>
public FloorId: string;
/// <summary>
/// 楼层名称
/// </summary>
public FloorName: string;
/// <summary>
/// 消防要素编号
/// </summary>
public FireElementId: string;
/// <summary>
/// 属性列表
/// </summary>
public PropertyInfos: PropertyInfo[];
/// <summary>
/// 交互方式
/// </summary>
public InteractiveMode: InteractiveMode;
/// <summary>
/// 是否来自建筑
/// </summary>
public IsFromBuilding: boolean;
/// <summary>
/// 渲染方式。
/// </summary>
public DrawMode: ImageType;
/// <summary>
/// 9宫格边框数值。
/// </summary>
public Border: Border;
/// <summary>
/// 厚度。
/// </summary>
public Thickness: number;
/// <summary>
/// 素材类型
/// </summary>
public GameMode: GameMode;
}
/**
*
*/
export enum FillMode {
Color,
Image
}
/**
*
*/
export enum InteractiveMode {
/**
*
*/
Single,
/**
*
*/
Multiple,
/**
*
*/
MultipleClosed
}
/**
*
*/
export enum ImageType {
Simple = 0,
Sliced = 1,
Tiled = 2,
Filled = 3
}
/**
*
*/
export class Border {
public x: number;
public y: number;
public z: number;
public w: number;
}

2
src/app/ui/collection-tools/collection-tools.component.ts

@ -431,7 +431,7 @@ export class CollectionToolsComponent implements OnInit {
let that = this let that = this
window.setTimeout(()=>{ window.setTimeout(()=>{
document.getElementById("functionalDomainContent").oncontextmenu = function (event) { document.getElementById("functionalDomainContent").oncontextmenu = function (event) {
that.canvas.cancelPaint() // that.canvas.cancelPaint()
that.selectImageIndex = -1 that.selectImageIndex = -1
event.preventDefault(); event.preventDefault();
}; };

836
src/app/working-area/charm.js

@ -0,0 +1,836 @@
export class Charm {
constructor(renderingEngine = PIXI) {
if (renderingEngine === undefined) throw new Error("Please assign a rendering engine in the constructor before using charm.js");
//Find out which rendering engine is being used (the default is Pixi)
this.renderer = "";
//If the `renderingEngine` is Pixi, set up Pixi object aliases
if (renderingEngine.ParticleContainer && renderingEngine.Sprite) {
this.renderer = "pixi";
}
//An array to store the global tweens
this.globalTweens = [];
//An object that stores all the easing formulas
this.easingFormulas = {
//Linear
linear(x) {
return x;
},
//Smoothstep
smoothstep(x) {
return x * x * (3 - 2 * x);
},
smoothstepSquared(x) {
return Math.pow((x * x * (3 - 2 * x)), 2);
},
smoothstepCubed(x) {
return Math.pow((x * x * (3 - 2 * x)), 3);
},
//Acceleration
acceleration(x) {
return x * x;
},
accelerationCubed(x) {
return Math.pow(x * x, 3);
},
//Deceleration
deceleration(x) {
return 1 - Math.pow(1 - x, 2);
},
decelerationCubed(x) {
return 1 - Math.pow(1 - x, 3);
},
//Sine
sine(x) {
return Math.sin(x * Math.PI / 2);
},
sineSquared(x) {
return Math.pow(Math.sin(x * Math.PI / 2), 2);
},
sineCubed(x) {
return Math.pow(Math.sin(x * Math.PI / 2), 2);
},
inverseSine(x) {
return 1 - Math.sin((1 - x) * Math.PI / 2);
},
inverseSineSquared(x) {
return 1 - Math.pow(Math.sin((1 - x) * Math.PI / 2), 2);
},
inverseSineCubed(x) {
return 1 - Math.pow(Math.sin((1 - x) * Math.PI / 2), 3);
},
//Spline
spline(t, p0, p1, p2, p3) {
return 0.5 * (
(2 * p1) +
(-p0 + p2) * t +
(2 * p0 - 5 * p1 + 4 * p2 - p3) * t * t +
(-p0 + 3 * p1 - 3 * p2 + p3) * t * t * t
);
},
//Bezier curve
cubicBezier(t, a, b, c, d) {
let t2 = t * t;
let t3 = t2 * t;
return a + (-a * 3 + t * (3 * a - a * t)) * t + (3 * b + t * (-6 * b + b * 3 * t)) * t + (c * 3 - c * 3 * t) * t2 + d * t3;
}
};
//Add `scaleX` and `scaleY` properties to Pixi sprites
this._addScaleProperties = (sprite) => {
if (this.renderer === "pixi") {
if (!("scaleX" in sprite) && ("scale" in sprite) && ("x" in sprite.scale)) {
Object.defineProperty(
sprite,
"scaleX", {
get() {
return sprite.scale.x
},
set(value) {
sprite.scale.x = value
}
}
);
}
if (!("scaleY" in sprite) && ("scale" in sprite) && ("y" in sprite.scale)) {
Object.defineProperty(
sprite,
"scaleY", {
get() {
return sprite.scale.y
},
set(value) {
sprite.scale.y = value
}
}
);
}
}
};
}
//The low level `tweenProperty` function is used as the foundation
//for the the higher level tween methods.
tweenProperty(
sprite, //Sprite object
property, //String property
startValue, //Tween start value
endValue, //Tween end value
totalFrames, //Duration in frames
type = "smoothstep", //The easing type
yoyo = false, //Yoyo?
delayBeforeRepeat = 0 //Delay in frames before repeating
) {
//Create the tween object
let o = {};
//If the tween is a bounce type (a spline), set the
//start and end magnitude values
let typeArray = type.split(" ");
if (typeArray[0] === "bounce") {
o.startMagnitude = parseInt(typeArray[1]);
o.endMagnitude = parseInt(typeArray[2]);
}
//Use `o.start` to make a new tween using the current
//end point values
o.start = (startValue, endValue) => {
//Clone the start and end values so that any possible references to sprite
//properties are converted to ordinary numbers
o.startValue = JSON.parse(JSON.stringify(startValue));
o.endValue = JSON.parse(JSON.stringify(endValue));
o.playing = true;
o.totalFrames = totalFrames;
o.frameCounter = 0;
//Add the tween to the global `tweens` array. The `tweens` array is
//updated on each frame
this.globalTweens.push(o);
};
//Call `o.start` to start the tween
o.start(startValue, endValue);
//The `update` method will be called on each frame by the game loop.
//This is what makes the tween move
o.update = () => {
let time, curvedTime;
if (o.playing) {
//If the elapsed frames are less than the total frames,
//use the tweening formulas to move the sprite
if (o.frameCounter < o.totalFrames) {
//Find the normalized value
let normalizedTime = o.frameCounter / o.totalFrames;
//Select the correct easing function from the
//`ease` object’s library of easing functions
//If it's not a spline, use one of the ordinary easing functions
if (typeArray[0] !== "bounce") {
curvedTime = this.easingFormulas[type](normalizedTime);
}
//If it's a spline, use the `spline` function and apply the
//2 additional `type` array values as the spline's start and
//end points
else {
curvedTime = this.easingFormulas.spline(normalizedTime, o.startMagnitude, 0, 1, o.endMagnitude);
}
//Interpolate the sprite's property based on the curve
sprite[property] = (o.endValue * curvedTime) + (o.startValue * (1 - curvedTime));
o.frameCounter += 1;
}
//When the tween has finished playing, run the end tasks
else {
sprite[property] = o.endValue;
o.end();
}
}
};
//The `end` method will be called when the tween is finished
o.end = () => {
//Set `playing` to `false`
o.playing = false;
//Call the tween's `onComplete` method, if it's been assigned
if (o.onComplete) o.onComplete();
//Remove the tween from the `tweens` array
this.globalTweens.splice(this.globalTweens.indexOf(o), 1);
//If the tween's `yoyo` property is `true`, create a new tween
//using the same values, but use the current tween's `startValue`
//as the next tween's `endValue`
if (yoyo) {
this.wait(delayBeforeRepeat).then(() => {
o.start(o.endValue, o.startValue);
});
}
};
//Pause and play methods
o.play = () => o.playing = true;
o.pause = () => o.playing = false;
//Return the tween object
return o;
}
//`makeTween` is a general low-level method for making complex tweens
//out of multiple `tweenProperty` functions. Its one argument,
//`tweensToAdd` is an array containing multiple `tweenProperty` calls
makeTween(tweensToAdd) {
//Create an object to manage the tweens
let o = {};
//Create a `tweens` array to store the new tweens
o.tweens = [];
//Make a new tween for each array
tweensToAdd.forEach(tweenPropertyArguments => {
//Use the tween property arguments to make a new tween
let newTween = this.tweenProperty(...tweenPropertyArguments);
//Push the new tween into this object's internal `tweens` array
o.tweens.push(newTween);
});
//Add a counter to keep track of the
//number of tweens that have completed their actions
let completionCounter = 0;
//`o.completed` will be called each time one of the tweens
//finishes
o.completed = () => {
//Add 1 to the `completionCounter`
completionCounter += 1;
//If all tweens have finished, call the user-defined `onComplete`
//method, if it's been assigned. Reset the `completionCounter`
if (completionCounter === o.tweens.length) {
if (o.onComplete) o.onComplete();
completionCounter = 0;
}
};
//Add `onComplete` methods to all tweens
o.tweens.forEach(tween => {
tween.onComplete = () => o.completed();
});
//Add pause and play methods to control all the tweens
o.pause = () => {
o.tweens.forEach(tween => {
tween.playing = false;
});
};
o.play = () => {
o.tweens.forEach(tween => {
tween.playing = true;
});
};
//Return the tween object
return o;
}
/* High level tween methods */
//1. Simple tweens
//`fadeOut`
fadeOut(sprite, frames = 60) {
return this.tweenProperty(
sprite, "alpha", sprite.alpha, 0, frames, "sine"
);
}
//`fadeIn`
fadeIn(sprite, frames = 60) {
return this.tweenProperty(
sprite, "alpha", sprite.alpha, 1, frames, "sine"
);
}
//`pulse`
//Fades the sprite in and out at a steady rate.
//Set the `minAlpha` to something greater than 0 if you
//don't want the sprite to fade away completely
pulse(sprite, frames = 60, minAlpha = 0) {
return this.tweenProperty(
sprite, "alpha", sprite.alpha, minAlpha, frames, "smoothstep", true
);
}
//2. Complex tweens
slide(
sprite, endX, endY,
frames = 60, type = "smoothstep", yoyo = false, delayBeforeRepeat = 0
) {
return this.makeTween([
//Create the x axis tween
[sprite, "x", sprite.x, endX, frames, type, yoyo, delayBeforeRepeat],
//Create the y axis tween
[sprite, "y", sprite.y, endY, frames, type, yoyo, delayBeforeRepeat]
]);
}
breathe(
sprite, endScaleX = 0.8, endScaleY = 0.8,
frames = 60, yoyo = true, delayBeforeRepeat = 0
) {
//Add `scaleX` and `scaleY` properties to Pixi sprites
this._addScaleProperties(sprite);
return this.makeTween([
//Create the scaleX tween
[
sprite, "scaleX", sprite.scaleX, endScaleX,
frames, "smoothstepSquared", yoyo, delayBeforeRepeat
],
//Create the scaleY tween
[
sprite, "scaleY", sprite.scaleY, endScaleY,
frames, "smoothstepSquared", yoyo, delayBeforeRepeat
]
]);
}
scale(sprite, endScaleX = 0.5, endScaleY = 0.5, frames = 60) {
//Add `scaleX` and `scaleY` properties to Pixi sprites
this._addScaleProperties(sprite);
return this.makeTween([
//Create the scaleX tween
[
sprite, "scaleX", sprite.scaleX, endScaleX,
frames, "smoothstep", false
],
//Create the scaleY tween
[
sprite, "scaleY", sprite.scaleY, endScaleY,
frames, "smoothstep", false
]
]);
}
strobe(
sprite, scaleFactor = 1.3, startMagnitude = 10, endMagnitude = 20,
frames = 10, yoyo = true, delayBeforeRepeat = 0
) {
let bounce = "bounce " + startMagnitude + " " + endMagnitude;
//Add `scaleX` and `scaleY` properties to Pixi sprites
this._addScaleProperties(sprite);
return this.makeTween([
//Create the scaleX tween
[
sprite, "scaleX", sprite.scaleX, scaleFactor, frames,
bounce, yoyo, delayBeforeRepeat
],
//Create the scaleY tween
[
sprite, "scaleY", sprite.scaleY, scaleFactor, frames,
bounce, yoyo, delayBeforeRepeat
]
]);
}
wobble(
sprite,
scaleFactorX = 1.2,
scaleFactorY = 1.2,
frames = 10,
xStartMagnitude = 10,
xEndMagnitude = 10,
yStartMagnitude = -10,
yEndMagnitude = -10,
friction = 0.98,
yoyo = true,
delayBeforeRepeat = 0
) {
let bounceX = "bounce " + xStartMagnitude + " " + xEndMagnitude;
let bounceY = "bounce " + yStartMagnitude + " " + yEndMagnitude;
//Add `scaleX` and `scaleY` properties to Pixi sprites
this._addScaleProperties(sprite);
let o = this.makeTween([
//Create the scaleX tween
[
sprite, "scaleX", sprite.scaleX, scaleFactorX, frames,
bounceX, yoyo, delayBeforeRepeat
],
//Create the scaleY tween
[
sprite, "scaleY", sprite.scaleY, scaleFactorY, frames,
bounceY, yoyo, delayBeforeRepeat
]
]);
//Add some friction to the `endValue` at the end of each tween
o.tweens.forEach(tween => {
tween.onComplete = () => {
//Add friction if the `endValue` is greater than 1
if (tween.endValue > 1) {
tween.endValue *= friction;
//Set the `endValue` to 1 when the effect is finished and
//remove the tween from the global `tweens` array
if (tween.endValue <= 1) {
tween.endValue = 1;
this.removeTween(tween);
}
}
};
});
return o;
}
//3. Motion path tweens
followCurve(
sprite,
pointsArray,
totalFrames,
type = "smoothstep",
yoyo = false,
delayBeforeRepeat = 0
) {
//Create the tween object
let o = {};
//If the tween is a bounce type (a spline), set the
//start and end magnitude values
let typeArray = type.split(" ");
if (typeArray[0] === "bounce") {
o.startMagnitude = parseInt(typeArray[1]);
o.endMagnitude = parseInt(typeArray[2]);
}
//Use `tween.start` to make a new tween using the current
//end point values
o.start = (pointsArray) => {
o.playing = true;
o.totalFrames = totalFrames;
o.frameCounter = 0;
//Clone the points array
o.pointsArray = JSON.parse(JSON.stringify(pointsArray));
//Add the tween to the `globalTweens` array. The `globalTweens` array is
//updated on each frame
this.globalTweens.push(o);
};
//Call `tween.start` to start the first tween
o.start(pointsArray);
//The `update` method will be called on each frame by the game loop.
//This is what makes the tween move
o.update = () => {
let normalizedTime, curvedTime,
p = o.pointsArray;
if (o.playing) {
//If the elapsed frames are less than the total frames,
//use the tweening formulas to move the sprite
if (o.frameCounter < o.totalFrames) {
//Find the normalized value
normalizedTime = o.frameCounter / o.totalFrames;
//Select the correct easing function
//If it's not a spline, use one of the ordinary tween
//functions
if (typeArray[0] !== "bounce") {
curvedTime = this.easingFormulas[type](normalizedTime);
}
//If it's a spline, use the `spline` function and apply the
//2 additional `type` array values as the spline's start and
//end points
else {
//curve = tweenFunction.spline(n, type[1], 0, 1, type[2]);
curvedTime = this.easingFormulas.spline(normalizedTime, o.startMagnitude, 0, 1, o.endMagnitude);
}
//Apply the Bezier curve to the sprite's position
sprite.x = this.easingFormulas.cubicBezier(curvedTime, p[0][0], p[1][0], p[2][0], p[3][0]);
sprite.y = this.easingFormulas.cubicBezier(curvedTime, p[0][1], p[1][1], p[2][1], p[3][1]);
//Add one to the `elapsedFrames`
o.frameCounter += 1;
}
//When the tween has finished playing, run the end tasks
else {
//sprite[property] = o.endValue;
o.end();
}
}
};
//The `end` method will be called when the tween is finished
o.end = () => {
//Set `playing` to `false`
o.playing = false;
//Call the tween's `onComplete` method, if it's been
//assigned
if (o.onComplete) o.onComplete();
//Remove the tween from the global `tweens` array
this.globalTweens.splice(this.globalTweens.indexOf(o), 1);
//If the tween's `yoyo` property is `true`, reverse the array and
//use it to create a new tween
if (yoyo) {
this.wait(delayBeforeRepeat).then(() => {
o.pointsArray = o.pointsArray.reverse();
o.start(o.pointsArray);
});
}
};
//Pause and play methods
o.pause = () => {
o.playing = false;
};
o.play = () => {
o.playing = true;
};
//Return the tween object
return o;
}
walkPath(
sprite, //The sprite
originalPathArray, //A 2D array of waypoints
totalFrames = 300, //The duration, in frames
type = "smoothstep", //The easing type
loop = false, //Should the animation loop?
yoyo = false, //Shoud the direction reverse?
delayBetweenSections = 0 //Delay, in milliseconds, between sections
) {
//Clone the path array so that any possible references to sprite
//properties are converted into ordinary numbers
let pathArray = JSON.parse(JSON.stringify(originalPathArray));
//Figure out the duration, in frames, of each path section by
//dividing the `totalFrames` by the length of the `pathArray`
let frames = totalFrames / pathArray.length;
//Set the current point to 0, which will be the first waypoint
let currentPoint = 0;
//The `makePath` function creates a single tween between two points and
//then schedules the next path to be made after it
let makePath = (currentPoint) => {
//Use the `makeTween` function to tween the sprite's
//x and y position
let tween = this.makeTween([
//Create the x axis tween between the first x value in the
//current point and the x value in the following point
[
sprite,
"x",
pathArray[currentPoint][0],
pathArray[currentPoint + 1][0],
frames,
type
],
//Create the y axis tween in the same way
[
sprite,
"y",
pathArray[currentPoint][1],
pathArray[currentPoint + 1][1],
frames,
type
]
]);
//When the tween is complete, advance the `currentPoint` by one.
//Add an optional delay between path segments, and then make the
//next connecting path
tween.onComplete = () => {
//Advance to the next point
currentPoint += 1;
//If the sprite hasn't reached the end of the
//path, tween the sprite to the next point
if (currentPoint < pathArray.length - 1) {
this.wait(delayBetweenSections).then(() => {
tween = makePath(currentPoint);
});
}
//If we've reached the end of the path, optionally
//loop and yoyo it
else {
//Reverse the path if `loop` is `true`
if (loop) {
//Reverse the array if `yoyo` is `true`
if (yoyo) pathArray.reverse();
//Optionally wait before restarting
this.wait(delayBetweenSections).then(() => {
//Reset the `currentPoint` to 0 so that we can
//restart at the first point
currentPoint = 0;
//Set the sprite to the first point
sprite.x = pathArray[0][0];
sprite.y = pathArray[0][1];
//Make the first new path
tween = makePath(currentPoint);
//... and so it continues!
});
}
}
};
//Return the path tween to the main function
return tween;
};
//Make the first path using the internal `makePath` function (below)
let tween = makePath(currentPoint);
//Pass the tween back to the main program
return tween;
}
walkCurve(
sprite, //The sprite
pathArray, //2D array of Bezier curves
totalFrames = 300, //The duration, in frames
type = "smoothstep", //The easing type
loop = false, //Should the animation loop?
yoyo = false, //Should the direction reverse?
delayBeforeContinue = 0 //Delay, in milliseconds, between sections
) {
//Divide the `totalFrames` into sections for each part of the path
let frames = totalFrames / pathArray.length;
//Set the current curve to 0, which will be the first one
let currentCurve = 0;
//The `makePath` function
let makePath = (currentCurve) => {
//Use the custom `followCurve` function to make
//a sprite follow a curve
let tween = this.followCurve(
sprite,
pathArray[currentCurve],
frames,
type
);
//When the tween is complete, advance the `currentCurve` by one.
//Add an optional delay between path segments, and then make the
//next path
tween.onComplete = () => {
currentCurve += 1;
if (currentCurve < pathArray.length) {
this.wait(delayBeforeContinue).then(() => {
tween = makePath(currentCurve);
});
}
//If we've reached the end of the path, optionally
//loop and reverse it
else {
if (loop) {
if (yoyo) {
//Reverse order of the curves in the `pathArray`
pathArray.reverse();
//Reverse the order of the points in each curve
pathArray.forEach(curveArray => curveArray.reverse());
}
//After an optional delay, reset the sprite to the
//beginning of the path and make the next new path
this.wait(delayBeforeContinue).then(() => {
currentCurve = 0;
sprite.x = pathArray[0][0];
sprite.y = pathArray[0][1];
tween = makePath(currentCurve);
});
}
}
};
//Return the path tween to the main function
return tween;
};
//Make the first path
let tween = makePath(currentCurve);
//Pass the tween back to the main program
return tween;
}
//4. Utilities
/*
The `wait` method lets you set up a timed sequence of events
wait(1000)
.then(() => console.log("One"))
.then(() => wait(1000))
.then(() => console.log("Two"))
.then(() => wait(1000))
.then(() => console.log("Three"))
*/
wait(duration = 0) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration);
});
}
//A utility to remove tweens from the game
removeTween(tweenObject) {
//Remove the tween if `tweenObject` doesn't have any nested
//tween objects
if (!tweenObject.tweens) {
tweenObject.pause();
//array.splice(-1,1) will always remove last elemnt of array, so this
//extra check prevents that (Thank you, MCumic10! https://github.com/kittykatattack/charm/issues/5)
if (this.globalTweens.indexOf(tweenObject) != -1) {
this.globalTweens.splice(this.globalTweens.indexOf(tweenObject), 1);
}
//Otherwise, remove the nested tween objects
} else {
tweenObject.pause();
tweenObject.tweens.forEach(element => {
this.globalTweens.splice(this.globalTweens.indexOf(element), 1);
});
}
}
update() {
//Update all the tween objects in the `globalTweens` array
if (this.globalTweens.length > 0) {
for (let i = this.globalTweens.length - 1; i >= 0; i--) {
let tween = this.globalTweens[i];
if (tween) tween.update();
}
}
}
}

62
src/app/working-area/model/PropertyInfo.ts

@ -0,0 +1,62 @@
/**
*
*/
export class PropertyInfo {
constructor(instanceData: any) {
this.Tag = instanceData.tag;
this.Order = instanceData.order;
this.Enabled = instanceData.enabled;
this.Visible = instanceData.visible;
this.Required = instanceData.required;
this.RuleName = instanceData.ruleName;
this.RuleValue = instanceData.ruleValue;
this.PhysicalUnit = instanceData.physicalUnit;
this.PropertyName = instanceData.propertyName;
this.PropertyType = instanceData.propertyType;
this.PropertyValue = instanceData.propertyValue;
}
/**
* ,
*/
public Tag: string;
/**
*
*/
public Order: number;
/**
*
*/
public Enabled: boolean;
/**
*
*/
public Visible: boolean;
/**
*
*/
public Required: boolean;
/**
*
*/
public RuleName: string;
/**
*
*/
public RuleValue: string;
/**
*
*/
public PhysicalUnit: string;
/**
*
*/
public PropertyName: string;
/**
*
*/
public PropertyType: number;
/**
*
*/
public PropertyValue: string;
}

41
src/app/working-area/model/arrows.ts

@ -0,0 +1,41 @@
import { WorkingAreaComponent } from '../working-area.component';
import * as PIXI from 'pixi.js';
/**
*
* 2
*/
export class Arrows extends PIXI.Container {
public line: PIXI.Graphics = new PIXI.Graphics();
public ready = false;
constructor(public assetData: any, private workingArea: WorkingAreaComponent) {
super();
this.workingArea.backgroundImage.addChild(this);
this.name = this.assetData.Id;
this.addChild(this.line);
this.refresh();
this.interactive = true;
this.on('mousedown', event => {
if (!this.ready) { return; }
event.stopPropagation();
this.workingArea.selection.selectOne(this);
});
}
/**
*
*/
public refresh() {
this.line.clear();
this.line.lineStyle(5, 0xff0000, 1);
this.line.moveTo(this.assetData.pointA.x, this.assetData.pointA.y);
this.line.lineTo(this.assetData.pointB.x, this.assetData.pointB.y);
const angle = Math.atan2((this.assetData.pointB.y - this.assetData.pointA.y), (this.assetData.pointB.x - this.assetData.pointA.x))
* (180 / Math.PI) + 90;
this.line.beginFill(0xff0000);
console.log(Math.PI / 180 / 1.6);
this.line.drawStar(this.assetData.pointB.x, this.assetData.pointB.y, 3, 10, 0, (Math.PI / 180 * angle));
this.line.endFill();
}
}

322
src/app/working-area/model/axArrowConnector.ts

@ -0,0 +1,322 @@
import { WorkingAreaComponent } from '../working-area.component';
import * as PIXI from 'pixi.js';
import { AxShape } from './axShape';
/**
*
*/
export class AxArrowConnector extends AxShape {
line: PIXI.Graphics;
text: PIXI.Text;
style = new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 18,
fontStyle: 'normal',
fontWeight: 'bold',
fill: ['#000000'],
stroke: '#ffffff',
strokeThickness: 3,
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 3,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 1,
wordWrap: false,
wordWrapWidth: 100,
});
pts: PIXI.Point[];
constructor(assetData: any, workingArea: WorkingAreaComponent) {
super(assetData, workingArea);
this.text = new PIXI.Text(this.assetData.Name
+ '\r\n'
+ this.assetData.PropertyInfos?.find((item: { PropertyName: string; }) =>
item.PropertyName === '名称/编号')?.PropertyValue, this.style);
this.line = new PIXI.Graphics();
this.addChild(this.text);
this.addChild(this.line);
this.workingArea.backgroundImage.addChild(this);
this.refresh(this.line, this.assetData.MultiPoint);
}
/**
*
*/
public refresh(c: PIXI.Graphics, pts: PIXI.Point[]): void {
if (pts.length < 2) {
this.text.position = pts[0];
return;
}
const strokeWidth = 1;
const startWidth = 30 + strokeWidth;
const endWidth = 30 + strokeWidth;
const edgeWidth = 10;
const openEnded = false;
const markerStart = false;// 起始箭头
const markerEnd = false;// 结束箭头
const spacing = (openEnded) ? 0 : 0 + strokeWidth / 2;
const startSize = 30 + strokeWidth;
const endSize = 30 + strokeWidth;
const isRounded = true;
const pe = pts[pts.length - 1];
let i0 = 1;
while (i0 < pts.length - 1 && pts[i0].x === pts[0].x && pts[i0].y === pts[0].y) {
i0++;
}
const dx = pts[i0].x - pts[0].x;
const dy = pts[i0].y - pts[0].y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) {
return;
}
let nx = dx / dist;
let nx1 = nx;
let nx2 = nx;
let ny = dy / dist;
let ny2 = ny;
let ny1 = ny;
let orthx = edgeWidth * ny;
let orthy = -edgeWidth * nx;
const fns = [];
// if (isRounded) {
// // c.setLineJoin('round');
// c.lineTextureStyle({ join: PIXI.LINE_JOIN.ROUND });
// } else if (pts.length > 2) {
// // Only mitre if there are waypoints
// // c.setMiterLimit(1.42);
// c.lineTextureStyle({ miterLimit: 1.42 });
// }
// c.lineStyle(1, 0x000000, 1);
c.clear();
c.lineTextureStyle({ width: 1, color: 0x00000, join: PIXI.LINE_JOIN.ROUND });
c.beginFill(0xffffff);
const startNx = nx;
const startNy = ny;
if (markerStart && !openEnded) {
this.paintMarker(c, pts[0].x, pts[0].y, nx, ny, startSize, startWidth, edgeWidth, spacing, true);
} else {
const outStartX = pts[0].x + orthx / 2 + spacing * nx;
const outStartY = pts[0].y + orthy / 2 + spacing * ny;
const inEndX = pts[0].x - orthx / 2 + spacing * nx;
const inEndY = pts[0].y - orthy / 2 + spacing * ny;
if (openEnded) {
c.moveTo(outStartX, outStartY);
fns.push( () => {
c.lineTo(inEndX, inEndY);
});
} else {
c.moveTo(inEndX, inEndY);
c.lineTo(outStartX, outStartY);
}
}
let dx1 = 0;
let dy1 = 0;
let dist1 = 0;
for (let i = 0; i < pts.length - 2; i++) {
const pos = this.relativeCcw(pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y, pts[i + 2].x, pts[i + 2].y);
dx1 = pts[i + 2].x - pts[i + 1].x;
dy1 = pts[i + 2].y - pts[i + 1].y;
dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
if (dist1 !== 0) {
nx1 = dx1 / dist1;
ny1 = dy1 / dist1;
const tmp1 = nx * nx1 + ny * ny1;
const tmp = Math.max(Math.sqrt((tmp1 + 1) / 2), 0.04);
nx2 = (nx + nx1);
ny2 = (ny + ny1);
const dist2 = Math.sqrt(nx2 * nx2 + ny2 * ny2);
if (dist2 !== 0) {
nx2 = nx2 / dist2;
ny2 = ny2 / dist2;
const strokeWidthFactor = Math.max(tmp, Math.min(1 / 200 + 0.04, 0.35));
const angleFactor = (pos !== 0 && isRounded) ? Math.max(0.1, strokeWidthFactor) : Math.max(tmp, 0.06);
const outX = pts[i + 1].x + ny2 * edgeWidth / 2 / angleFactor;
const outY = pts[i + 1].y - nx2 * edgeWidth / 2 / angleFactor;
const inX = pts[i + 1].x - ny2 * edgeWidth / 2 / angleFactor;
const inY = pts[i + 1].y + nx2 * edgeWidth / 2 / angleFactor;
if (pos === 0 || !isRounded) {
c.lineTo(outX, outY);
((x, y) => {
fns.push(() => {
c.lineTo(x, y);
});
})(inX, inY);
} else if (pos === -1) {
const c1x = inX + ny * edgeWidth;
const c1y = inY - nx * edgeWidth;
const c2x = inX + ny1 * edgeWidth;
const c2y = inY - nx1 * edgeWidth;
c.lineTo(c1x, c1y);
if (isRounded) {
c.quadraticCurveTo(outX, outY, c2x, c2y); // 圆角
} else {
c.lineTo(outX, outY);
}
((x, y) => {
fns.push(() => {
c.lineTo(x, y);
});
})(inX, inY);
} else {
c.lineTo(outX, outY);
((x, y) => {
const c1x = outX - ny * edgeWidth;
const c1y = outY + nx * edgeWidth;
const c2x = outX - ny1 * edgeWidth;
const c2y = outY + nx1 * edgeWidth;
fns.push(() => {
if (isRounded) {
c.quadraticCurveTo(x, y, c1x, c1y);
} else {
c.lineTo(x, y);
}
});
fns.push(() => {
c.lineTo(c2x, c2y);
});
})(inX, inY);
}
nx = nx1;
ny = ny1;
}
}
}
orthx = edgeWidth * ny1;
orthy = - edgeWidth * nx1;
if (markerEnd && !openEnded) {
this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, false);
} else {
c.lineTo(pe.x - spacing * nx1 + orthx / 2, pe.y - spacing * ny1 + orthy / 2);
const inStartX = pe.x - spacing * nx1 - orthx / 2;
const inStartY = pe.y - spacing * ny1 - orthy / 2;
if (!openEnded) {
c.lineTo(inStartX, inStartY);
} else {
c.moveTo(inStartX, inStartY);
fns.splice(0, 0, () => {
c.moveTo(inStartX, inStartY);
});
}
}
for (let i = fns.length - 1; i >= 0; i--) {
fns[i]();
}
c.closePath();
c.endFill();
// if (openEnded)
// {
// c.end();
// c.stroke();
// }
// else
// {
// c.close();
// c.fillAndStroke();
// }
// c.setShadow(false);
// c.setMiterLimit(4);
// if (isRounded)
// {
// c.setLineJoin('flat');
// }
// if (pts.length > 2)
// {
// c.setMiterLimit(4);
// if (markerStart && !openEnded)
// {
// c.begin();
// this.paintMarker(c, pts[0].x, pts[0].y, startNx, startNy, startSize, startWidth, edgeWidth, spacing, true);
// c.stroke();
// c.end();
// }
// if (markerEnd && !openEnded)
// {
// c.begin();
// this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, true);
// c.stroke();
// c.end();
// }
// }
}
paintMarker(c: PIXI.Graphics, ptX: number, ptY: number, nx: number, ny: number,
size: number, arrowWidth: number, edgeWidth: number, spacing: number, initialMove: boolean) {
const widthArrowRatio = edgeWidth / arrowWidth;
const orthx = edgeWidth * ny / 2;
const orthy = -edgeWidth * nx / 2;
const spaceX = (spacing + size) * nx;
const spaceY = (spacing + size) * ny;
if (initialMove) {
c.moveTo(ptX - orthx + spaceX, ptY - orthy + spaceY);
} else {
c.lineTo(ptX - orthx + spaceX, ptY - orthy + spaceY);
}
c.lineTo(ptX - orthx / widthArrowRatio + spaceX, ptY - orthy / widthArrowRatio + spaceY);
c.lineTo(ptX + spacing * nx, ptY + spacing * ny);
c.lineTo(ptX + orthx / widthArrowRatio + spaceX, ptY + orthy / widthArrowRatio + spaceY);
c.lineTo(ptX + orthx + spaceX, ptY + orthy + spaceY);
}
relativeCcw(x1: number, y1: number, x2: number, y2: number, px: number, py: number) {
x2 -= x1;
y2 -= y1;
px -= x1;
py -= y1;
let ccw = px * y2 - py * x2;
if (ccw === 0.0) {
ccw = px * x2 + py * y2;
if (ccw > 0.0) {
px -= x2;
py -= y2;
ccw = px * x2 + py * y2;
if (ccw < 0.0) {
ccw = 0.0;
}
}
}
return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0);
}
redraw(): void{
this.refresh(this.line, this.assetData.MultiPoint);
}
}

443
src/app/working-area/model/axImageShape.ts

@ -0,0 +1,443 @@
import { WorkingAreaComponent } from '../working-area.component';
import * as ObjectID from 'bson-objectid';
import { GameMode } from './gameMode';
import { Pipeline } from './pipeline';
import { PaintMode } from './paintModel';
import * as PIXI from 'pixi.js';
import { PropertyInfo } from './PropertyInfo';
import { AxShape } from './axShape';
import { Sprite } from 'pixi.js';
/**
*
* AxImageShape
*/
export class AxImageShape extends AxShape {
style = new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 18,
fontStyle: 'normal',
fontWeight: 'bold',
fill: ['#000000'],
stroke: '#ffffff',
strokeThickness: 3,
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 3,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 1,
wordWrap: false,
wordWrapWidth: 100,
});
text = new PIXI.Text(this.assetData.Name
+ '\r\n'
+ this.assetData.PropertyInfos?.find(item => item.PropertyName === '名称/编号')?.PropertyValue, this.style);
/**
*
*/
image: PIXI.Sprite;
selectionBox = new PIXI.Graphics();
connectPointTexture = PIXI.Texture.from('assets/images/handle-secondary.png');
connectPoint: Sprite;
// 可移动的
// 可选中的
// up: PIXI.Sprite;
// down: PIXI.Sprite;
// left: PIXI.Sprite;
// right: PIXI.Sprite;
// upLeft: PIXI.Sprite;
// upRight: PIXI.Sprite;
// downLeft: PIXI.Sprite;
// downRight: PIXI.Sprite;
constructor(assetData: any, workingArea: WorkingAreaComponent) {
super(assetData, workingArea);
this.x = this.assetData.Point.x;
this.y = this.assetData.Point.y;
this.name = this.assetData.Id;
this.image = PIXI.Sprite.from(this.assetData.ImageUrl);
this.image.angle = this.assetData.Angle;
this.image.x = 0;
this.image.y = 0;
this.image.width = this.assetData.Width;
this.image.height = this.assetData.Height;
this.image.alpha = 1;
this.image.anchor.set(0.5);
// this.image.interactive = true;
// this.image.buttonMode = true;
// this.image
// .on('mousedown', event => {
// event.stopPropagation();
// this.workingArea.selection.selectOne(this);
// // this.paintingPipeline(this.x, this.y);
// // 如果链接对象不为空,禁止移动
// if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) {
// event.currentTarget.parent.data = event.data;
// event.currentTarget.parent.alpha = 0.5;
// event.currentTarget.parent.dragging = true;
// }
// })
// .on('mouseup', event => {
// if (event.currentTarget.parent.dragging) {
// event.currentTarget.parent.alpha = 1;
// event.currentTarget.parent.dragging = false;
// event.currentTarget.parent.data = null;
// }
// })
// .on('mouseupoutside', event => {
// if (event.currentTarget.parent.dragging) {
// event.currentTarget.parent.alpha = 1;
// event.currentTarget.parent.dragging = false;
// event.currentTarget.parent.data = null;
// }
// })
// .on('mousemove', event => {
// if (event.currentTarget.parent.dragging) {
// // // 如果拖动过程中发现父对象不是背景图
// // if (this.parent !== this.workingArea.backgroundImage) {
// // this.setParent(this.workingArea.backgroundImage);
// // if (this.assetData.FixedSize) {
// // const scale = 1 / this.workingArea.backgroundImage.scale.x;
// // this.scale.set(scale);
// // }
// // }
// const newPosition = event.currentTarget.parent.data.getLocalPosition(event.currentTarget.parent.parent);
// event.currentTarget.parent.x = newPosition.x;
// event.currentTarget.parent.y = newPosition.y;
// this.assetData.Point = new PIXI.Point(this.x, this.y);
// this.workingArea.canvasData.isChange = true;
// }
// })
// .on('rightclick', event => {
// })
// .on('mouseover', event => {
// event.stopPropagation();
// if (this.workingArea.previewImage !== null
// && this.workingArea.getPaintMode() === PaintMode.singlePointIcon) {
// this.workingArea.previewImage.visible = false;
// }
// // if (this.assetData.CanConnect) {
// // this.setSelectionBox(true, this.image);
// // }
// })
// .on('mouseout', event => {
// event.stopPropagation();
// if (this.workingArea.previewImage !== null
// && this.workingArea.getPaintMode() === PaintMode.singlePointIcon) {
// this.workingArea.previewImage.visible = true;
// }
// // if (this.assetData.CanConnect) {
// // this.setSelectionBox(false);
// // }
// });
this.text.x = this.image.x;
this.text.y = this.image.y - this.image.height / 2;
this.text.anchor.set(0.5, 1);
if (this.assetData.GameMode === 2) {
this.text.visible = false;
}
this.addChild(this.text);
this.addChild(this.image);
this.addChild(this.selectionBox);
if (this.assetData.CanConnect) {
// connectPoint
this.connectPoint = new PIXI.Sprite(this.connectPointTexture);
this.connectPoint.anchor.set(0.5);
this.connectPoint.x = this.image.x;
this.connectPoint.y = this.image.y;
this.addChild(this.connectPoint);
this.connectPoint.interactive = true;
this.connectPoint
.on('mousedown', event => {
event.stopPropagation();
this.paintingPipeline(this.x, this.y);
})
.on('mouseover', event => {
this.setSelectionBox(true, this.connectPoint);
})
.on('mouseout', event => {
this.setSelectionBox(false);
});
// // up
// this.up = new PIXI.Sprite(this.selectedPointTexture);
// this.up.anchor.set(0.5);
// this.up.x = this.image.x;
// this.up.y = this.image.y - (this.image.height / 2);
// this.addChild(this.up);
// this.up.interactive = true;
// this.up
// .on('mousedown', event => {
// event.stopPropagation();
// const pt = this.toGlobal(new PIXI.Point(this.up.x, this.up.y));
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
// this.paintingPipeline(pt2.x, pt2.y);
// })
// .on('mouseover', event => {
// this.setSelectionBox(true, this.up);
// })
// .on('mouseout', event => {
// this.setSelectionBox(false);
// });
// // down
// this.down = new PIXI.Sprite(this.selectedPointTexture);
// this.down.anchor.set(0.5);
// this.down.x = this.image.x;
// this.down.y = this.image.y + (this.image.height / 2);
// this.addChild(this.down);
// this.down.interactive = true;
// this.down
// .on('mousedown', event => {
// event.stopPropagation();
// const pt = this.toGlobal(new PIXI.Point(this.down.x, this.down.y));
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
// this.paintingPipeline(pt2.x, pt2.y);
// })
// .on('mouseover', event => {
// this.setSelectionBox(true, this.down);
// })
// .on('mouseout', event => {
// this.setSelectionBox(false);
// });
// // left
// this.left = new PIXI.Sprite(this.selectedPointTexture);
// this.left.anchor.set(0.5);
// this.left.x = this.image.x - (this.image.width / 2);
// this.left.y = this.image.y;
// this.addChild(this.left);
// this.left.interactive = true;
// this.left
// .on('mousedown', event => {
// event.stopPropagation();
// const pt = this.toGlobal(new PIXI.Point(this.left.x, this.left.y));
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
// this.paintingPipeline(pt2.x, pt2.y);
// })
// .on('mouseover', event => {
// this.setSelectionBox(true, this.left);
// })
// .on('mouseout', event => {
// this.setSelectionBox(false);
// });
// // right
// this.right = new PIXI.Sprite(this.selectedPointTexture);
// this.right.anchor.set(0.5);
// this.right.x = this.image.x + (this.image.width / 2);
// this.right.y = this.image.y;
// this.addChild(this.right);
// this.right.interactive = true;
// this.right
// .on('mousedown', event => {
// event.stopPropagation();
// const pt = this.toGlobal(new PIXI.Point(this.right.x, this.right.y));
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
// this.paintingPipeline(pt2.x, pt2.y);
// })
// .on('mouseover', event => {
// this.setSelectionBox(true, this.right);
// })
// .on('mouseout', event => {
// this.setSelectionBox(false);
// });
// // up-left
// this.upLeft = new PIXI.Sprite(this.selectedPointTexture);
// this.upLeft.anchor.set(0.5);
// this.upLeft.x = this.image.x - (this.image.width / 2);
// this.upLeft.y = this.image.y - (this.image.height / 2);
// this.addChild(this.upLeft);
// this.upLeft.interactive = true;
// this.upLeft
// .on('mousedown', event => {
// event.stopPropagation();
// const pt = this.toGlobal(new PIXI.Point(this.upLeft.x, this.upLeft.y));
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
// this.paintingPipeline(pt2.x, pt2.y);
// })
// .on('mouseover', event => {
// this.setSelectionBox(true, this.upLeft);
// })
// .on('mouseout', event => {
// this.setSelectionBox(false);
// });
// // up-right
// this.upRight = new PIXI.Sprite(this.selectedPointTexture);
// this.upRight.anchor.set(0.5);
// this.upRight.x = this.image.x + (this.image.width / 2);
// this.upRight.y = this.image.y - (this.image.height / 2);
// this.addChild(this.upRight);
// this.upRight.interactive = true;
// this.upRight
// .on('mousedown', event => {
// event.stopPropagation();
// const pt = this.toGlobal(new PIXI.Point(this.upRight.x, this.upRight.y));
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
// this.paintingPipeline(pt2.x, pt2.y);
// })
// .on('mouseover', event => {
// this.setSelectionBox(true, this.upRight);
// })
// .on('mouseout', event => {
// this.setSelectionBox(false);
// });
// // down-left
// this.downLeft = new PIXI.Sprite(this.selectedPointTexture);
// this.downLeft.anchor.set(0.5);
// this.downLeft.x = this.image.x - (this.image.width / 2);
// this.downLeft.y = this.image.y + (this.image.height / 2);
// this.addChild(this.downLeft);
// this.downLeft.interactive = true;
// this.downLeft
// .on('mousedown', event => {
// event.stopPropagation();
// const pt = this.toGlobal(new PIXI.Point(this.downLeft.x, this.downLeft.y));
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
// this.paintingPipeline(pt2.x, pt2.y);
// })
// .on('mouseover', event => {
// this.setSelectionBox(true, this.downLeft);
// })
// .on('mouseout', event => {
// this.setSelectionBox(false);
// });
// // down-right
// this.downRight = new PIXI.Sprite(this.selectedPointTexture);
// this.downRight.anchor.set(0.5);
// this.downRight.x = this.image.x + (this.image.width / 2);
// this.downRight.y = this.image.y + (this.image.height / 2);
// this.addChild(this.downRight);
// this.downRight.interactive = true;
// this.downRight
// .on('mousedown', event => {
// event.stopPropagation();
// const pt = this.toGlobal(new PIXI.Point(this.downRight.x, this.downRight.y));
// const pt2 = this.workingArea.backgroundImage.toLocal(pt);
// this.paintingPipeline(pt2.x, pt2.y);
// })
// .on('mouseover', event => {
// this.setSelectionBox(true, this.downRight);
// })
// .on('mouseout', event => {
// this.setSelectionBox(false);
// });
this.showConnectionPoint(false);
}
}
// 设置选择框
public setSelectionBox(b: boolean, sprite?: PIXI.Sprite) {
if (b) {
this.selectionBox.lineStyle(2, 0x00EB00, 1);
this.selectionBox.position = sprite.position;
this.selectionBox.drawRect(- sprite.width / 2, - sprite.height / 2, sprite.width, sprite.height);
// const p0 = new PIXI.Point(- sprite.width / 2, - sprite.height / 2);
// const pe = new PIXI.Point(sprite.width / 2, sprite.height / 2);
// const pw = new PIXI.Point(p0.x + sprite.width, p0.y);
// const ph = new PIXI.Point(p0.x, p0.y + sprite.height);
// this.drawDashedLine(this.selectionBox, p0, pw, 0x1234ff);
// this.drawDashedLine(this.selectionBox, p0, ph, 0x1234ff);
// this.drawDashedLine(this.selectionBox, pe, pw, 0x1234ff);
// this.drawDashedLine(this.selectionBox, pe, ph, 0x1234ff);
} else {
this.selectionBox.clear();
}
}
// 设置名称
public setNameVisible(value: boolean, mode: GameMode) {
if (this.assetData.GameMode === mode) {
this.text.visible = value;
}
}
// 显示连接点
public showConnectionPoint(b: boolean) {
this.connectPoint.visible = b;
// this.up.visible = b;
// this.down.visible = b;
// this.left.visible = b;
// this.right.visible = b;
// this.upLeft.visible = b;
// this.downLeft.visible = b;
// this.upRight.visible = b;
// this.downRight.visible = b;
}
paintingPipeline(x: number, y: number) {
if (this.assetData.CanConnect) {
if (this.workingArea.getPaintMode() === PaintMode.Pipeline) {
if (this.workingArea.paintingPipeline === null) {
this.workingArea.previewLineSegment.visible = true;
this.workingArea.currentClickPoint.position =
new PIXI.Point(this.workingArea.circleShadow.x, this.workingArea.circleShadow.y);
this.workingArea.paintPoints.push(new PIXI.Point(x, y));
const json = JSON.parse(JSON.stringify(this.workingArea.canvasData.selectTemplateData.propertyInfos));
const list = [];
json.forEach(element => {
const property = new PropertyInfo(element);
list.push(property);
});
const tempData = {
TemplateId: this.workingArea.canvasData.selectTemplateData.id,
CanConnect: this.workingArea.canvasData.selectTemplateData.canConnect,
Pipelines: new Array(),
FloorId: this.workingArea.canvasData.selectStorey.id,
Angle: this.workingArea.canvasData.selectTemplateData.angle,
Color: this.workingArea.canvasData.selectTemplateData.color,
Enabled: this.workingArea.canvasData.selectTemplateData.enabled,
FillMode: this.workingArea.canvasData.selectTemplateData.fillMode,
FireElementId: this.workingArea.canvasData.selectTemplateData.fireElementId,
FixedSize: this.workingArea.canvasData.selectTemplateData.fixedSize,
Height : 32,
Width : 32,
Id: ObjectID.default.generate(),
ImageUrl: this.workingArea.canvasData.selectTemplateData.imageUrl,
InteractiveMode: this.workingArea.canvasData.selectTemplateData.interactiveMode,
MultiPoint : JSON.parse(JSON.stringify(this.workingArea.paintPoints)),
Point: new PIXI.Point(0, 0),
Name : this.workingArea.canvasData.selectTemplateData.name,
PropertyInfos: list,
Border : this.workingArea.canvasData.selectTemplateData.border,
DrawMode : this.workingArea.canvasData.selectTemplateData.drawMode,
Thickness : this.workingArea.canvasData.selectTemplateData.thickness,
IsFromBuilding : this.workingArea.canvasData.selectTemplateData.isFromBuilding,
GameMode: this.workingArea.canvasData.gameMode,
LinkedObjects: new Array(this.assetData.Id),
};
this.workingArea.paintingPipeline = new Pipeline(tempData, this.workingArea);
this.assetData.Pipelines.push(this.workingArea.paintingPipeline.assetData.Id);
this.workingArea.emit('createIcon', this.workingArea.paintingPipeline);
} else {
this.workingArea.previewLineSegment.visible = false;
this.workingArea.currentClickPoint.position =
new PIXI.Point(this.workingArea.circleShadow.x, this.workingArea.circleShadow.y);
this.workingArea.paintPoints.push(new PIXI.Point(x, y));
this.workingArea.paintingPipeline.assetData.MultiPoint =
JSON.parse(JSON.stringify(this.workingArea.paintPoints));
this.workingArea.paintingPipeline.assetData.LinkedObjects.push(this.assetData.Id);
this.assetData.Pipelines.push(this.workingArea.paintingPipeline.assetData.Id);
this.workingArea.paintingPipeline.refresh();
this.workingArea.initPipelineData();
}
}
}
}
// 刷新
public refresh() {
if (this.assetData.CanConnect) {
}
this.image.width = this.assetData.Width;
this.image.height = this.assetData.Height;
this.image.angle = this.assetData.Angle;
this.text.text = this.assetData.Name
+ '\r\n'
+ this.assetData.PropertyInfos?.find(item => item.PropertyName === '名称/编号')?.PropertyValue;
this.text.x = this.image.x;
this.text.y = this.image.y - this.image.height / 2;
}
}

27
src/app/working-area/model/axPreviewImageShape.ts

@ -0,0 +1,27 @@
import { Sprite, Texture } from 'pixi.js';
import { WorkingAreaComponent } from '../working-area.component';
import { AxShape } from './axShape';
export class AxPreviewImageShape extends AxShape {
image: Sprite = null;
/**
*
*/
constructor(workingArea: WorkingAreaComponent) {
super(null, workingArea);
this.image = new Sprite();
this.image.width = 32;
this.image.height = 32;
this.image.anchor.set(0.5);
this.interactive = false;
this.scale.set(1 / this.workingArea.backgroundImage.scale.x);
this.addChild(this.image);
}
/**
*
* @param url
*/
setImageUrl(url: string) {
this.image.texture = Texture.from(url);
}
}

76
src/app/working-area/model/axShape.ts

@ -0,0 +1,76 @@
import { Constructor } from '@angular/material/core/common-behaviors/constructor';
import * as PIXI from 'pixi.js';
import { Point, Rectangle, Graphics, Container } from 'pixi.js';
import { WorkingAreaComponent } from '../working-area.component';
/**
*
*/
export class AxShape extends Container {
assetData: any;
workingArea: WorkingAreaComponent;
// 可以被移动的
moveable = true;
// 可以被选中的
selectable = true;
constructor(assetData: any, workingArea: WorkingAreaComponent) {
super();
this.assetData = assetData;
this.workingArea = workingArea;
this.workingArea.backgroundImage.addChild(this);
this.interactive = true;
this.buttonMode = true;
this.on('mousedown', event => {
console.log(this.assetData);
event.stopPropagation();
if (this.selectable) {
this.workingArea.selection.selectOne(this);
}
if (this.moveable) {
event.currentTarget.data = event.data;
event.currentTarget.alpha = 0.5;
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;
}
})
.on('mouseup', event => {
if (event.currentTarget.dragging) {
event.currentTarget.alpha = 1;
event.currentTarget.dragging = false;
event.currentTarget.data = null;
}
})
.on('mouseupoutside', event => {
if (event.currentTarget.dragging) {
event.currentTarget.alpha = 1;
event.currentTarget.dragging = false;
event.currentTarget.data = null;
}
})
.on('mousemove', event => {
if (event.currentTarget.dragging) {
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;
this.assetData.Point = new PIXI.Point(this.x, this.y);
this.workingArea.canvasData.isChange = true;
}
})
.on('rightclick', event => {
})
.on('mouseover', event => {
event.stopPropagation();
})
.on('mouseout', event => {
event.stopPropagation();
});
}
redraw(): void {
}
}

7
src/app/working-area/model/gameMode.ts

@ -0,0 +1,7 @@
/**
*
*/
export enum GameMode {
BasicInformation,
Assignment
}

246
src/app/working-area/model/multipointIcon.ts

@ -0,0 +1,246 @@
import { WorkingAreaComponent } from '../working-area.component';
import { GameMode } from './gameMode';
import * as PIXI from 'pixi.js';
/**
* 线
*/
export class MultipointIcon extends PIXI.Container {
public pointsData: PIXI.Point[];
public pointsGraphics: PIXI.Graphics[] = [];
public iconsTilingSprite: PIXI.TilingSprite[] = [];
style = new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 18,
fontStyle: 'normal',
fontWeight: 'bold',
fill: ['#000000'],
stroke: '#ffffff',
strokeThickness: 3,
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 3,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 1,
wordWrap: false,
wordWrapWidth: 100,
});
public text = new PIXI.Text(this.assetData.Name
+ '\r\n'
+ this.assetData.PropertyInfos?.find(item => item.PropertyName === '名称/编号')?.PropertyValue, this.style);
/**
*
* @param texture
* @param points
*/
constructor(public assetData: any, private workingArea: WorkingAreaComponent) {
super();
this.name = this.assetData.Id;
this.pointsData = this.assetData.MultiPoint;
this.x = this.assetData.Point.x;
this.y = this.assetData.Point.y;
this.workingArea.backgroundImage.addChild(this);
// 画线图标
for (let i = 0, count = this.pointsData.length - 1; i < count; i++) {
const pointA = this.pointsData[i];
const pointB = this.pointsData[i + 1];
const angle = Math.atan2((pointB.y - pointA.y), (pointB.x - pointA.x)) * (180 / Math.PI);
const a = pointB.x - pointA.x;
const b = pointB.y - pointA.y;
const distance = Math.sqrt(a * a + b * b);
const icon = new PIXI.TilingSprite(PIXI.Texture.from(this.assetData.ImageUrl), distance, 64);
icon.anchor.set(0, 0.5);
icon.x = pointA.x;
icon.y = pointA.y;
icon.angle = angle;
icon.height = this.assetData.Thickness === 0 ? 32 : this.assetData.Thickness;
this.iconsTilingSprite.push(icon);
this.addChild(icon);
if (i === 0) {
this.text.anchor.set(0.5);
this.text.position = icon.position;
this.text.y -= this.assetData.Height;
this.addChild(this.text);
}
}
// 画点
this.pointsData.forEach((item, index, array) => {
const iconPoint = new PIXI.Graphics();
iconPoint.lineStyle(1, 0xFFBD01, 1);
iconPoint.beginFill(0xFFFFFF, 1);
iconPoint.drawCircle(0, 0, 15);
iconPoint.x = item.x;
iconPoint.y = item.y;
iconPoint.endFill();
iconPoint.visible = false;
this.pointsGraphics.push(iconPoint);
this.addChild(iconPoint);
});
// 添加圆点事件
this.pointsGraphics.forEach((item, index, array) => {
item.interactive = true;
item.on('mousedown', event => {
event.stopPropagation();
if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) {
event.currentTarget.data = event.data;
event.currentTarget.alpha = 0.5;
event.currentTarget.dragging = true;
}
})
.on('mouseup', event => {
if (event.currentTarget.dragging) {
event.currentTarget.alpha = 1;
event.currentTarget.dragging = false;
event.currentTarget.data = null;
}
})
.on('mouseupoutside', event => {
if (event.currentTarget.dragging) {
event.currentTarget.alpha = 1;
event.currentTarget.dragging = false;
event.currentTarget.data = null;
}
})
.on('mousemove', event => {
if (event.currentTarget.dragging) {
const newPosition = event.currentTarget.data.getLocalPosition(event.currentTarget.parent);
event.currentTarget.x = newPosition.x;
event.currentTarget.y = newPosition.y;
this.assetData.MultiPoint[index].x = newPosition.x;
this.assetData.MultiPoint[index].y = newPosition.y;
this.workingArea.canvasData.isChange = true;
if (index === 0) {// 第一个点
this.iconsTilingSprite[index].x = newPosition.x;
this.iconsTilingSprite[index].y = newPosition.y;
const pointA = array[index];
const pointB = array[index + 1];
const angle = Math.atan2((pointB.y - pointA.y), (pointB.x - pointA.x)) * (180 / Math.PI);
const a = pointB.x - pointA.x;
const b = pointB.y - pointA.y;
const distance = Math.sqrt(a * a + b * b);
this.iconsTilingSprite[index].angle = angle;
this.iconsTilingSprite[index].width = distance;
this.text.position = this.iconsTilingSprite[index].position;
this.text.y -= this.assetData.Height;
} else if (index < array.length - 1) {// 不是第一个点,也不是最后一个点
this.iconsTilingSprite[index].x = newPosition.x;
this.iconsTilingSprite[index].y = newPosition.y;
const pointA = array[index]; // 当前点
const pointB = array[index + 1]; // 后一个点
const pointC = array[index - 1]; // 前一个点
const angle = Math.atan2((pointB.y - pointA.y), (pointB.x - pointA.x)) * (180 / Math.PI);
const a = pointB.x - pointA.x;
const b = pointB.y - pointA.y;
const distance = Math.sqrt(a * a + b * b);
this.iconsTilingSprite[index].angle = angle;
this.iconsTilingSprite[index].width = distance;
const angleC = Math.atan2((pointA.y - pointC.y), (pointA.x - pointC.x)) * (180 / Math.PI);
const aC = pointA.x - pointC.x;
const bC = pointA.y - pointC.y;
const distanceC = Math.sqrt(aC * aC + bC * bC);
this.iconsTilingSprite[index - 1].angle = angleC;
this.iconsTilingSprite[index - 1].width = distanceC;
} else if (index === array.length - 1) { // 最后一个点
const pointA = array[index]; // 当前点
const pointC = array[index - 1]; // 前一个点
const angleC = Math.atan2((pointA.y - pointC.y), (pointA.x - pointC.x)) * (180 / Math.PI);
const aC = pointA.x - pointC.x;
const bC = pointA.y - pointC.y;
const distanceC = Math.sqrt(aC * aC + bC * bC);
this.iconsTilingSprite[index - 1].angle = angleC;
this.iconsTilingSprite[index - 1].width = distanceC;
}
}
})
.on('rightclick', event => {
});
});
// // 缩放
// this.workingArea.on('backgroundScale', data => {
// const scale = 1 / data;
// this.text.scale.set(scale);
// });
// 添加选中事件
this.iconsTilingSprite.forEach((item, index, array) => {
item.interactive = true;
item.buttonMode = true;
item.on('mousedown', event => {
event.stopPropagation();
this.workingArea.selection.selectOne(this);
if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) {
event.currentTarget.parent.data = event.data;
event.currentTarget.parent.alpha = 0.5;
event.currentTarget.parent.dragging = true;
event.currentTarget.parent.dragPoint = event.data.getLocalPosition(event.currentTarget.parent.parent);
event.currentTarget.parent.dragPoint.x -= event.currentTarget.parent.x;
event.currentTarget.parent.dragPoint.y -= event.currentTarget.parent.y;
}
})
.on('mouseup', event => {
if (event.currentTarget.parent.dragging) {
event.currentTarget.parent.alpha = 1;
event.currentTarget.parent.dragging = false;
event.currentTarget.parent.data = null;
}
})
.on('mouseupoutside', event => {
if (event.currentTarget.parent.dragging) {
event.currentTarget.parent.alpha = 1;
event.currentTarget.parent.dragging = false;
event.currentTarget.parent.data = null;
}
})
.on('mousemove', event => {
if (event.currentTarget.parent.dragging) {
const newPosition = event.currentTarget.parent.data.getLocalPosition(event.currentTarget.parent.parent);
event.currentTarget.parent.x = newPosition.x - event.currentTarget.parent.dragPoint.x;
event.currentTarget.parent.y = newPosition.y - event.currentTarget.parent.dragPoint.y;
this.assetData.Point = new PIXI.Point(this.x, this.y);
this.workingArea.canvasData.isChange = true;
}
})
.on('rightclick', event => {
});
});
}
/**
*
* @param value
*/
public setPointVisiable(value: boolean) {
this.pointsGraphics.forEach((item) => {
item.visible = value;
});
}
// 设置名称
public setNameVisible(value: boolean, mode: GameMode) {
if (this.assetData.GameMode === mode) {
this.text.visible = value;
}
}
// 刷新数据
public refresh() {
console.log(this.assetData);
this.iconsTilingSprite.forEach(element => {
element.height = this.assetData.Thickness === 0 ? 32 : this.assetData.Thickness;
});
this.text.text = this.assetData.Name
+ '\r\n'
+ this.assetData.PropertyInfos.find(item => item.PropertyName === '名称/编号')?.PropertyValue;
}
}

33
src/app/working-area/model/paintModel.ts

@ -0,0 +1,33 @@
/**
*
*/
export enum PaintMode {
/**
*
*/
singlePointIcon,
/**
* 线
*/
lineIcon,
/**
*
*/
polygonIcon,
/**
*
*/
Pipeline,
/**
*
*/
endPaint,
/**
*
*/
Arrows,
/**
*
*/
Car,
}

328
src/app/working-area/model/pipeline.ts

@ -0,0 +1,328 @@
import { WorkingAreaComponent } from '../working-area.component';
import * as PIXI from 'pixi.js';
import { AxShape } from './axShape';
/**
* 线
*/
export class Pipeline extends AxShape {
public line: PIXI.Graphics = new PIXI.Graphics();
constructor(assetData: any, workingArea: WorkingAreaComponent) {
super(assetData, workingArea);
this.name = this.assetData.Id;
this.moveable = false;
this.x = this.assetData.Point.x;
this.y = this.assetData.Point.y;
this.workingArea.backgroundImage.addChild(this);
this.addChild(this.line);
// 画线图标
this.refresh();
this.interactive = true;
this.on('mousedown', event => {
event.stopPropagation();
this.workingArea.selection.selectOne(this);
});
}
/**
*
*/
public refresh() {
const strokeWidth = 1;
const startWidth = 30 + strokeWidth;
const endWidth = 30 + strokeWidth;
const edgeWidth = 10;
const openEnded = false;
const markerStart = false;
const markerEnd = true;
const spacing = (openEnded) ? 0 : 0 + strokeWidth / 2;
const startSize = 30 + strokeWidth;
const endSize = 30 + strokeWidth;
const isRounded = true;
const pts = this.assetData.MultiPoint;
const c = this.line;
if (pts.length < 2) { return; }
// Base vector (between first points)
const pe = pts[pts.length - 1];
// Finds first non-overlapping point
let i0 = 1;
while (i0 < pts.length - 1 && pts[i0].x === pts[0].x && pts[i0].y === pts[0].y) {
i0++;
}
const dx = pts[i0].x - pts[0].x;
const dy = pts[i0].y - pts[0].y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist === 0) {
return;
}
// Computes the norm and the inverse norm
let nx = dx / dist;
let nx1 = nx;
let nx2 = nx;
let ny = dy / dist;
let ny2 = ny;
let ny1 = ny;
let orthx = edgeWidth * ny;
let orthy = -edgeWidth * nx;
// Stores the inbound function calls in reverse order in fns
const fns = [];
// if (isRounded) {
// // c.setLineJoin('round');
// c.lineTextureStyle({ join: PIXI.LINE_JOIN.ROUND });
// } else if (pts.length > 2) {
// // Only mitre if there are waypoints
// // c.setMiterLimit(1.42);
// c.lineTextureStyle({ miterLimit: 1.42 });
// }
// c.lineStyle(1, 0x000000, 1);
c.clear();
c.lineTextureStyle({ width: 1, color: 0x00000, join: PIXI.LINE_JOIN.ROUND });
// c.begin();
c.beginFill(0xffffff);
const startNx = nx;
const startNy = ny;
if (markerStart && !openEnded) {
this.paintMarker(c, pts[0].x, pts[0].y, nx, ny, startSize, startWidth, edgeWidth, spacing, true);
} else {
const outStartX = pts[0].x + orthx / 2 + spacing * nx;
const outStartY = pts[0].y + orthy / 2 + spacing * ny;
const inEndX = pts[0].x - orthx / 2 + spacing * nx;
const inEndY = pts[0].y - orthy / 2 + spacing * ny;
if (openEnded) {
c.moveTo(outStartX, outStartY);
fns.push( () => {
c.lineTo(inEndX, inEndY);
});
} else {
c.moveTo(inEndX, inEndY);
c.lineTo(outStartX, outStartY);
}
}
let dx1 = 0;
let dy1 = 0;
let dist1 = 0;
for (let i = 0; i < pts.length - 2; i++) {
// Work out in which direction the line is bending
const pos = this.relativeCcw(pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y, pts[i + 2].x, pts[i + 2].y);
dx1 = pts[i + 2].x - pts[i + 1].x;
dy1 = pts[i + 2].y - pts[i + 1].y;
dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
if (dist1 !== 0) {
nx1 = dx1 / dist1;
ny1 = dy1 / dist1;
const tmp1 = nx * nx1 + ny * ny1;
const tmp = Math.max(Math.sqrt((tmp1 + 1) / 2), 0.04);
// Work out the normal orthogonal to the line through the control point and the edge sides intersection
nx2 = (nx + nx1);
ny2 = (ny + ny1);
const dist2 = Math.sqrt(nx2 * nx2 + ny2 * ny2);
if (dist2 !== 0) {
nx2 = nx2 / dist2;
ny2 = ny2 / dist2;
// Higher strokewidths require a larger minimum bend, 0.35 covers all but the most extreme cases
const strokeWidthFactor = Math.max(tmp, Math.min(1 / 200 + 0.04, 0.35));
const angleFactor = (pos !== 0 && isRounded) ? Math.max(0.1, strokeWidthFactor) : Math.max(tmp, 0.06);
const outX = pts[i + 1].x + ny2 * edgeWidth / 2 / angleFactor;
const outY = pts[i + 1].y - nx2 * edgeWidth / 2 / angleFactor;
const inX = pts[i + 1].x - ny2 * edgeWidth / 2 / angleFactor;
const inY = pts[i + 1].y + nx2 * edgeWidth / 2 / angleFactor;
if (pos === 0 || !isRounded) {
// If the two segments are aligned, or if we're not drawing curved sections between segments
// just draw straight to the intersection point
c.lineTo(outX, outY);
((x, y) => {
fns.push(() => {
c.lineTo(x, y);
});
})(inX, inY);
} else if (pos === -1) {
const c1x = inX + ny * edgeWidth;
const c1y = inY - nx * edgeWidth;
const c2x = inX + ny1 * edgeWidth;
const c2y = inY - nx1 * edgeWidth;
c.lineTo(c1x, c1y);
if (isRounded) {
c.quadraticCurveTo(outX, outY, c2x, c2y); // 圆角
} else {
c.lineTo(outX, outY);
}
((x, y) => {
fns.push(() => {
c.lineTo(x, y);
});
})(inX, inY);
} else {
c.lineTo(outX, outY);
((x, y) => {
const c1x = outX - ny * edgeWidth;
const c1y = outY + nx * edgeWidth;
const c2x = outX - ny1 * edgeWidth;
const c2y = outY + nx1 * edgeWidth;
fns.push(() => {
if (isRounded) {
c.quadraticCurveTo(x, y, c1x, c1y);
} else {
c.lineTo(x, y);
}
});
fns.push(() => {
c.lineTo(c2x, c2y);
});
})(inX, inY);
}
nx = nx1;
ny = ny1;
}
}
}
orthx = edgeWidth * ny1;
orthy = - edgeWidth * nx1;
if (markerEnd && !openEnded) {
this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, false);
} else {
c.lineTo(pe.x - spacing * nx1 + orthx / 2, pe.y - spacing * ny1 + orthy / 2);
const inStartX = pe.x - spacing * nx1 - orthx / 2;
const inStartY = pe.y - spacing * ny1 - orthy / 2;
if (!openEnded) {
c.lineTo(inStartX, inStartY);
} else {
c.moveTo(inStartX, inStartY);
fns.splice(0, 0, () => {
c.moveTo(inStartX, inStartY);
});
}
}
for (let i = fns.length - 1; i >= 0; i--) {
fns[i]();
}
c.closePath();
c.endFill();
// if (openEnded)
// {
// c.end();
// c.stroke();
// }
// else
// {
// c.close();
// c.fillAndStroke();
// }
// Workaround for shadow on top of base arrow
// c.setShadow(false);
// Need to redraw the markers without the low miter limit
// c.setMiterLimit(4);
// if (isRounded)
// {
// c.setLineJoin('flat');
// }
// if (pts.length > 2) {
// // Only to repaint markers if no waypoints
// // Need to redraw the markers without the low miter limit
// // c.setMiterLimit(4);
// c.lineTextureStyle({ width: 1, color: 0x00000, miterLimit: 4 });
// if (markerStart && !openEnded) {
// // c.begin();
// this.paintMarker(c, pts[0].x, pts[0].y, startNx, startNy, startSize, startWidth, edgeWidth, spacing, true);
// // c.stroke();
// // c.end();
// // c.closePath();
// }
// if (markerEnd && !openEnded) {
// // c.begin();
// this.paintMarker(c, pe.x, pe.y, -nx, -ny, endSize, endWidth, edgeWidth, spacing, true);
// // c.stroke();
// // c.end();
// // c.closePath();
// }
// }
}
/**
*
* @param c
* @param ptX
* @param ptY
* @param nx
* @param ny
* @param size
* @param arrowWidth
* @param edgeWidth
* @param spacing
* @param initialMove
*/
paintMarker(c: PIXI.Graphics, ptX: number, ptY: number, nx: number, ny: number,
size: number, arrowWidth: number, edgeWidth: number, spacing: number, initialMove: boolean) {
const widthArrowRatio = edgeWidth / arrowWidth;
const orthx = edgeWidth * ny / 2;
const orthy = -edgeWidth * nx / 2;
const spaceX = (spacing + size) * nx;
const spaceY = (spacing + size) * ny;
if (initialMove) {
c.moveTo(ptX - orthx + spaceX, ptY - orthy + spaceY);
} else {
c.lineTo(ptX - orthx + spaceX, ptY - orthy + spaceY);
}
c.lineTo(ptX - orthx / widthArrowRatio + spaceX, ptY - orthy / widthArrowRatio + spaceY);
c.lineTo(ptX + spacing * nx, ptY + spacing * ny);
c.lineTo(ptX + orthx / widthArrowRatio + spaceX, ptY + orthy / widthArrowRatio + spaceY);
c.lineTo(ptX + orthx + spaceX, ptY + orthy + spaceY);
}
relativeCcw(x1: number, y1: number, x2: number, y2: number, px: number, py: number) {
x2 -= x1;
y2 -= y1;
px -= x1;
py -= y1;
let ccw = px * y2 - py * x2;
if (ccw === 0.0) {
ccw = px * x2 + py * y2;
if (ccw > 0.0) {
px -= x2;
py -= y2;
ccw = px * x2 + py * y2;
if (ccw < 0.0) {
ccw = 0.0;
}
}
}
return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0);
}
}

269
src/app/working-area/model/polygonIcon.ts

@ -0,0 +1,269 @@
import { WorkingAreaComponent } from '../working-area.component';
import { GameMode } from './gameMode';
import * as PIXI from 'pixi.js';
import { PaintMode } from './paintModel';
/**
*
*/
export class PolygonIcon extends PIXI.Container {
public pointsData: PIXI.Point[];
public pointsGraphics: PIXI.Graphics[] = [];
public polygonGraphics: PIXI.Graphics = new PIXI.Graphics();
public polygonLineGraphics: PIXI.Graphics = new PIXI.Graphics();
style = new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 18,
fontStyle: 'normal',
fontWeight: 'bold',
fill: ['#000000'],
stroke: '#ffffff',
strokeThickness: 3,
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 3,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 1,
wordWrap: false,
wordWrapWidth: 100,
});
public text = new PIXI.Text(this.assetData.Name
+ '\r\n'
+ this.assetData.PropertyInfos.find(item => item.PropertyName === '名称/编号')?.PropertyValue, this.style);
/**
*
* @param points
*/
constructor(public assetData: any, private workingArea: WorkingAreaComponent) {
super();
this.name = this.assetData.Id;
this.x = this.assetData.Point.x;
this.y = this.assetData.Point.y;
this.pointsData = this.assetData.MultiPoint;
this.workingArea.backgroundImage.addChild(this);
this.sortableChildren = true;
// 画点
this.pointsData.forEach((item, index, array) => {
const iconPoint = new PIXI.Graphics();
iconPoint.lineStyle(1, 0xFFBD01, 1);
iconPoint.beginFill(0xFFFFFF, 1);
iconPoint.drawCircle(0, 0, 15);
iconPoint.x = item.x;
iconPoint.y = item.y;
iconPoint.endFill();
iconPoint.visible = false;
this.pointsGraphics.push(iconPoint);
this.addChild(iconPoint);
});
// 填充多边形
const color: number = this.assetData.Color.substring(0, 7).replace('#', '0x');
const angle: number = parseInt(this.assetData.Color.substring(7), 16) / 255;
this.polygonGraphics.beginFill(color, angle);
this.polygonGraphics.drawPolygon(this.getPoints());
this.polygonGraphics.endFill();
this.addChild(this.polygonGraphics);
// 画多边形
this.polygonLineGraphics.lineStyle(5, 0xFFBD01, 1);
this.polygonLineGraphics.drawPolygon(this.getPoints());
this.polygonLineGraphics.closePath();
this.addChild(this.polygonLineGraphics);
this.text.anchor.set(0.5);
this.text.position = this.calculatePolygonGravityCenter(this.pointsData);
// console.log(this.calculatePolygonGravityCenter(this.pointsData));
this.polygonGraphics.addChild(this.text);
// 添加圆点事件
this.pointsGraphics.forEach((item, index, array) => {
item.interactive = true;
item.buttonMode = true;
item.zIndex = 1;
item.on('mousedown', event => {
event.stopPropagation();
if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) {
event.currentTarget.data = event.data;
event.currentTarget.alpha = 0.5;
event.currentTarget.dragging = true;
}
})
.on('mouseup', event => {
if (event.currentTarget.dragging) {
event.currentTarget.alpha = 1;
event.currentTarget.dragging = false;
event.currentTarget.data = null;
}
})
.on('mouseupoutside', event => {
if (event.currentTarget.dragging) {
event.currentTarget.alpha = 1;
event.currentTarget.dragging = false;
event.currentTarget.data = null;
}
})
.on('mousemove', event => {
if (event.currentTarget.dragging) {
const newPosition = event.currentTarget.data.getLocalPosition(event.currentTarget.parent);
event.currentTarget.x = newPosition.x;
event.currentTarget.y = newPosition.y;
this.assetData.MultiPoint[index].x = newPosition.x;
this.assetData.MultiPoint[index].y = newPosition.y;
this.workingArea.canvasData.isChange = true;
// 填充多边形
this.polygonGraphics.clear();
this.polygonGraphics.beginFill(color, angle);
this.polygonGraphics.drawPolygon(this.getPoints());
this.polygonGraphics.endFill();
// 画多边形
this.polygonLineGraphics.clear();
this.polygonLineGraphics.lineStyle(5, 0xFFBD01, 1);
this.polygonLineGraphics.drawPolygon(this.getPoints());
this.polygonLineGraphics.closePath();
this.text.position = this.calculatePolygonGravityCenter(this.pointsData);
}
})
.on('rightclick', event => {
}) .on('mouseover', event => {
event.stopPropagation();
if (this.workingArea.previewImage !== null
&& this.workingArea.getPaintMode() === PaintMode.singlePointIcon) {
this.workingArea.previewImage.visible = false;
}
})
.on('mouseout', event => {
event.stopPropagation();
if (this.workingArea.previewImage !== null
&& this.workingArea.getPaintMode() === PaintMode.singlePointIcon) {
this.workingArea.previewImage.visible = true;
}
});
});
// 添加选中事件
this.polygonGraphics.interactive = true;
this.polygonGraphics.buttonMode = true;
this.polygonGraphics
.on('mousedown', event => {
event.stopPropagation();
this.workingArea.selection.selectOne(this);
if (this.workingArea.allowEdit && this.assetData.GameMode === this.workingArea.canvasData.gameMode) {
event.currentTarget.parent.data = event.data;
event.currentTarget.parent.alpha = 0.5;
event.currentTarget.parent.dragging = true;
event.currentTarget.parent.dragPoint = event.data.getLocalPosition(event.currentTarget.parent.parent);
event.currentTarget.parent.dragPoint.x -= event.currentTarget.parent.x;
event.currentTarget.parent.dragPoint.y -= event.currentTarget.parent.y;
}
})
.on('mouseup', event => {
if (event.currentTarget.parent.dragging) {
event.currentTarget.parent.alpha = 1;
event.currentTarget.parent.dragging = false;
event.currentTarget.parent.data = null;
}
})
.on('mouseupoutside', event => {
if (event.currentTarget.parent.dragging) {
event.currentTarget.parent.alpha = 1;
event.currentTarget.parent.dragging = false;
event.currentTarget.parent.data = null;
}
})
.on('mousemove', event => {
if (event.currentTarget.parent.dragging) {
const newPosition = event.currentTarget.parent.data.getLocalPosition(event.currentTarget.parent.parent);
event.currentTarget.parent.x = newPosition.x - event.currentTarget.parent.dragPoint.x;
event.currentTarget.parent.y = newPosition.y - event.currentTarget.parent.dragPoint.y;
this.assetData.Point = new PIXI.Point(this.x, this.y);
this.workingArea.canvasData.isChange = true;
}
})
.on('rightclick', event => {
// this.workingArea.selection.deselectAll();
})
.on('mouseover', event => {
event.stopPropagation();
if (this.workingArea.previewImage !== null
&& this.workingArea.getPaintMode() === PaintMode.singlePointIcon) {
this.workingArea.previewImage.visible = false;
}
})
.on('mouseout', event => {
event.stopPropagation();
if (this.workingArea.previewImage !== null
&& this.workingArea.getPaintMode() === PaintMode.singlePointIcon) {
this.workingArea.previewImage.visible = true;
}
});
}
/**
*
* @param value
*/
public setPointVisiable(value: boolean) {
this.pointsGraphics.forEach((item) => {
item.visible = value;
});
}
public calculatePolygonGravityCenter(points: PIXI.Point[]) {
let area = 0.0; // 多边形面积
let gravityLat = 0.0; // 重心点 latitude
let gravityLng = 0.0; // 重心点 longitude
points.forEach((item, index) => {
// 1
const lat = item.x;
const lng = item.y;
const nextLat = points[(index + 1) % points.length].x;
const nextLng = points[(index + 1) % points.length].y;
// 2
const tempArea = (nextLat * lng - nextLng * lat) / 2.0;
// 3
area += tempArea;
// 4
gravityLat += tempArea * (lat + nextLat) / 3;
gravityLng += tempArea * (lng + nextLng) / 3;
});
// 5
gravityLat = gravityLat / area;
gravityLng = gravityLng / area;
return new PIXI.Point(gravityLat, gravityLng);
}
/**
*
*/
public getPoints(): PIXI.Point[] {
const points: PIXI.Point[] = [];
this.pointsGraphics.forEach(item => {
points.push(item.position);
});
return points;
}
/**
*
* @param value true/false /
* @param mode BasicInformation = 0
* Assignment想定作业 = 1
*/
public setNameVisible(value: boolean, mode: GameMode) {
if (this.assetData.GameMode === mode) {
this.text.visible = value;
}
}
public refresh() {
this.text.text = this.assetData.Name
+ '\r\n'
+ this.assetData.PropertyInfos.find(item => item.PropertyName === '名称/编号')?.PropertyValue;
// 填充多边形
const color: number = this.assetData.Color.substring(0, 7).replace('#', '0x');
const angle: number = parseInt(this.assetData.Color.substring(7), 16) / 255;
this.polygonGraphics.clear();
this.polygonGraphics.beginFill(color, angle);
this.polygonGraphics.drawPolygon(this.getPoints());
this.polygonGraphics.endFill();
}
}

59
src/app/working-area/model/putCarArea.ts

@ -0,0 +1,59 @@
// import { OldFilmFilter } from 'pixi-filters';
// import { WorkingAreaComponent } from '../working-area.component';
// import { PaintMode } from './paintModel';
// import { SinglePointIcon } from './axImageShape';
// import * as PIXI from 'pixi.js';
// /**
// * 汽车放置区域
// */
// export class PutCarArea extends PIXI.Container {
// public polygonGraphics: PIXI.Graphics = new PIXI.Graphics();
// constructor(public assetData: any, private workingArea: WorkingAreaComponent) {
// super();
// this.name = this.assetData.Id;
// this.x = this.assetData.Point.x;
// this.y = this.assetData.Point.y;
// this.workingArea.backgroundImage.addChild(this);
// this.sortableChildren = true;
// // 填充多边形
// const color: number = this.assetData.Color.substring(0, 7).replace('#', '0x');
// const angle: number = parseInt(this.assetData.Color.substring(7), 16) / 255;
// this.polygonGraphics.beginFill(color, angle);
// this.polygonGraphics.drawPolygon(this.assetData.MultiPoint);
// this.polygonGraphics.endFill();
// this.addChild(this.polygonGraphics);
// // 添加选中事件
// this.polygonGraphics.interactive = true;
// this.polygonGraphics
// .on('pointerdown', (event) => {
// if (this.workingArea.getPaintMode() === PaintMode.Car) {
// this.workingArea.selectCar.Point =
// new PIXI.Point(this.workingArea.previewSinglePointIcon.x, this.workingArea.previewSinglePointIcon.y);
// this.workingArea.selectCar.Angle = this.assetData.Direction;
// const car = new SinglePointIcon(this.workingArea.selectCar, this.workingArea);
// this.workingArea.setPaintMode(PaintMode.endPaint);
// }
// })
// .on('pointerup', (event) => {
// })
// .on('pointerupoutside', (event) => {
// })
// .on('pointerover', (event) => {
// this.workingArea.previewSinglePointIcon.filters = null;
// this.workingArea.previewSinglePointIcon.zIndex = this.zIndex + 1;
// // 设置车辆方向
// this.workingArea.previewSinglePointIcon.angle = this.assetData.Direction;
// console.log(this.assetData.Name);
// })
// .on('pointerout', (event) => {
// this.workingArea.previewSinglePointIcon.filters = [
// new OldFilmFilter()
// ];
// });
// }
// }

1400
src/app/working-area/working-area.component.ts

File diff suppressed because it is too large Load Diff

BIN
src/assets/images/enterPaintButton.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

BIN
src/assets/images/enterPaintButton.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
src/assets/images/testBackground.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Loading…
Cancel
Save