56 changed files with 3942 additions and 1499 deletions
@ -0,0 +1,32 @@
|
||||
<!-- |
||||
* @Descripttion: |
||||
* @version: |
||||
* @Author: sueRimn |
||||
* @Date: 2021-02-23 14:49:48 |
||||
* @LastEditors: sueRimn |
||||
* @LastEditTime: 2021-02-23 15:38:47 |
||||
--> |
||||
<div class="box"> |
||||
<div class="diaone"> |
||||
<div style="margin-bottom: 5px;"><label>请填写修改后的试卷名称:</label></div> |
||||
<div><input placeholder="请填写" [(ngModel)]="examName"></div> |
||||
</div> |
||||
<div class="diatwo"> |
||||
<div class="starttime"> |
||||
<div style="margin-bottom: 5px;"><label>请选择开始时间:</label></div> |
||||
<!-- <div><nz-range-picker class="datepicker" nzFormat="yyyy-MM-dd HH:mm" [nzShowTime]="{ nzHideDisabledOptions: true, nzDefaultOpenValue: timeDefaultValue }" [nzDisabledTime]="disabledDateTime" [(ngModel)]="date" (ngModelChange)="onChange($event)"></nz-range-picker> |
||||
</div> --> |
||||
<div><input type="datetime-local" name="start_time" [(ngModel)]="startTime" /></div> |
||||
</div> |
||||
<div class="endtime"> |
||||
<div style="margin-bottom: 5px;"><label>请选择结束时间:</label></div> |
||||
<div><input type="datetime-local" name="end_time" [(ngModel)]="endTime"/></div> |
||||
</div> |
||||
|
||||
</div> |
||||
|
||||
<div mat-dialog-actions style="margin-top: 20px;"> |
||||
<button mat-button (click)="onNoClick()" style="background-color: #07CDCF;margin-left: 200px;color: #fff;">确定</button> |
||||
<button mat-button type="button" (click)="close()" style=" background-color: #FF8678;margin-left: 25px;color: #fff;">取消</button> |
||||
</div> |
||||
</div> |
@ -0,0 +1,44 @@
|
||||
.box{ |
||||
display: flex; |
||||
flex-direction: column; |
||||
margin-left: 20px; |
||||
input{ |
||||
width: 260px; |
||||
height: 40px; |
||||
line-height: 34px; |
||||
border-radius: 5px; |
||||
padding-left: 5px; |
||||
outline: none; |
||||
border: 1px solid rgb(226, 211, 211); |
||||
} |
||||
.diaone{ |
||||
display: flex; |
||||
flex-direction: column; |
||||
|
||||
button { |
||||
border: none; |
||||
color: white; |
||||
padding: 5px 25px; |
||||
text-align: center; |
||||
text-decoration: none; |
||||
display: inline-block; |
||||
font-size: 16px; |
||||
margin: 4px 2px; |
||||
cursor: pointer; |
||||
border-radius: 8px; |
||||
outline:0 none !important; |
||||
} |
||||
} |
||||
.diatwo{ |
||||
margin-top: 20px; |
||||
display: flex; |
||||
flex-direction: row; |
||||
.endtime{ |
||||
margin-left: 20px; |
||||
} |
||||
.datepicker{ |
||||
height: 44px; |
||||
border-radius: 5px; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@
|
||||
<!-- |
||||
* @Descripttion: |
||||
* @version: |
||||
* @Author: sueRimn |
||||
* @Date: 2021-02-23 14:49:48 |
||||
* @LastEditors: sueRimn |
||||
* @LastEditTime: 2021-02-23 15:38:47 |
||||
--> |
||||
<div class="box"> |
||||
<div class="diaone"> |
||||
<div style="margin-bottom: 5px;"><label>请填写修改后的试卷名称:</label></div> |
||||
<div><input placeholder="请填写" [(ngModel)]="examName"></div> |
||||
</div> |
||||
<div class="diatwo"> |
||||
<div class="starttime"> |
||||
<div style="margin-bottom: 5px;"><label>请选择开始时间:</label></div> |
||||
<!-- <div><nz-range-picker class="datepicker" nzFormat="yyyy-MM-dd HH:mm" [nzShowTime]="{ nzHideDisabledOptions: true, nzDefaultOpenValue: timeDefaultValue }" [nzDisabledTime]="disabledDateTime" [(ngModel)]="date" (ngModelChange)="onChange($event)"></nz-range-picker> |
||||
</div> --> |
||||
<div><input type="datetime-local" name="start_time" [(ngModel)]="startTime" /></div> |
||||
</div> |
||||
<div class="endtime"> |
||||
<div style="margin-bottom: 5px;"><label>请选择结束时间:</label></div> |
||||
<div><input type="datetime-local" name="end_time" [(ngModel)]="endTime"/></div> |
||||
</div> |
||||
|
||||
</div> |
||||
|
||||
<div mat-dialog-actions style="margin-top: 20px;"> |
||||
<button mat-button (click)="onNoClick()" style="background-color: #07CDCF;margin-left: 200px;color: #fff;">确定</button> |
||||
<button mat-button type="button" (click)="close()" style=" background-color: #FF8678;margin-left: 25px;color: #fff;">取消</button> |
||||
</div> |
||||
</div> |
@ -1,48 +1,50 @@
|
||||
<h2 mat-dialog-title>创建用户</h2> |
||||
<h2 mat-dialog-title>新增用户</h2> |
||||
|
||||
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container"> |
||||
|
||||
<div> |
||||
<mat-form-field> |
||||
<input matInput id="idNumber" name="idNumber" |
||||
required ngModel placeholder="请输入身份证号" autocomplete="off" pattern="^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$"> |
||||
<mat-error> |
||||
<strong>请输入正确身份证号</strong> |
||||
</mat-error> |
||||
<input matInput id="realName" name="realName" required ngModel placeholder="用户姓名" autocomplete="off"> |
||||
</mat-form-field> |
||||
</div> |
||||
|
||||
<div> |
||||
<mat-form-field> |
||||
<input matInput id="realName" name="realName" |
||||
maxlength="100" |
||||
required ngModel placeholder="请输入真实姓名" autocomplete="off"> |
||||
<input matInput id="identityCard" name="identityCard" required ngModel placeholder="身份证号" autocomplete="off" pattern="^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$"> |
||||
</mat-form-field> |
||||
</div> |
||||
|
||||
<div> |
||||
<mat-form-field> |
||||
<mat-select placeholder="请选择职务" [formControl]="toppings" multiple required> |
||||
<div style="float: left;"> |
||||
<mat-option *ngFor="let item of detachmentPosts" [value]="item.id">{{item.name}}</mat-option> |
||||
</div> |
||||
<div style="float: left;"> |
||||
<mat-option *ngFor="let item of brigadePosts" [value]="item.id">{{item.name}}</mat-option> |
||||
</div> |
||||
<div style="float: left;"> |
||||
<mat-option *ngFor="let item of RescueStationPosts" [value]="item.id">{{item.name}}</mat-option> |
||||
</div> |
||||
</mat-select> |
||||
<input matInput id="phone" name="phone" required ngModel placeholder="手机号" type="number" autocomplete="off" pattern="^(?:\+?86)?1(?:3\d{3}|5[^4\D]\d{2}|8\d{3}|7(?:[0-35-9]\d{2}|4(?:0\d|1[0-2]|9\d))|9[0-35-9]\d{2}|6[2567]\d{2}|4(?:[14]0\d{3}|[68]\d{4}|[579]\d{2}))\d{6}$"> |
||||
</mat-form-field> |
||||
</div> |
||||
|
||||
|
||||
<div style="margin-bottom: 10px;"> |
||||
<p style="font-size: 14px;">消防救援站: <label style="margin-left: 10px;">{{organizationName}}</label></p> |
||||
</div> |
||||
|
||||
<div class="treeDiv"> |
||||
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl"> |
||||
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding (click)='selectTree(node)'> |
||||
<button type="button" mat-icon-button disabled ></button> |
||||
<li>{{node.name}}</li> |
||||
</mat-tree-node> |
||||
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding (click)='selectTree(node)'> |
||||
<button type="button" mat-icon-button matTreeNodeToggle [attr.aria-label]="'toggle ' + node.name"> |
||||
<mat-icon mat-icon class="mat-icon-rtl-mirror">{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}</mat-icon> |
||||
</button> |
||||
<li>{{node.name}}</li> |
||||
</mat-tree-node> |
||||
</mat-tree> |
||||
</div> |
||||
|
||||
<div mat-dialog-content *ngIf="errmsg"> |
||||
<p style="font-size: 14px; color: red;">{{errmsg}}</p> |
||||
</div> |
||||
|
||||
<div mat-dialog-actions> |
||||
<button mat-raised-button color="primary" type="submit" [disabled]="!form.form.valid || toppings.value == null">确定</button> |
||||
<button mat-raised-button color="primary" type="submit" [disabled]="!form.form.valid">确定</button> |
||||
<button mat-raised-button mat-dialog-close>取消</button> |
||||
</div> |
||||
|
||||
|
@ -1,48 +1,44 @@
|
||||
<h2 mat-dialog-title>创建教员</h2> |
||||
<h2 mat-dialog-title>新增用户</h2> |
||||
|
||||
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container"> |
||||
|
||||
<div> |
||||
<mat-form-field> |
||||
<input matInput id="idNumber" name="idNumber" |
||||
required ngModel placeholder="请输入帐号" autocomplete="off" pattern="^[a-zA-Z][a-zA-Z0-9_]{4,19}$"> |
||||
<mat-error> |
||||
<strong>帐号格式为字母+数字</strong> |
||||
</mat-error> |
||||
<input matInput id="name" name="name" required ngModel placeholder="登录账号" autocomplete="off" pattern="^[a-zA-Z][a-zA-Z0-9_]{4,19}$"> |
||||
</mat-form-field> |
||||
</div> |
||||
|
||||
<div> |
||||
<mat-form-field> |
||||
<input matInput id="realName" name="realName" |
||||
maxlength="100" |
||||
required ngModel placeholder="请输入真实姓名" autocomplete="off"> |
||||
<input matInput id="realName" name="realName" required ngModel placeholder="用户姓名" autocomplete="off"> |
||||
</mat-form-field> |
||||
</div> |
||||
|
||||
<div> |
||||
<mat-form-field> |
||||
<mat-select placeholder="请选择职务" [formControl]="toppings" multiple required> |
||||
<div style="float: left;"> |
||||
<mat-option *ngFor="let item of detachmentPosts" [value]="item.id">{{item.name}}</mat-option> |
||||
</div> |
||||
<div style="float: left;"> |
||||
<mat-option *ngFor="let item of brigadePosts" [value]="item.id">{{item.name}}</mat-option> |
||||
</div> |
||||
<div style="float: left;"> |
||||
<mat-option *ngFor="let item of RescueStationPosts" [value]="item.id">{{item.name}}</mat-option> |
||||
</div> |
||||
</mat-select> |
||||
</mat-form-field> |
||||
<div style="margin-bottom: 10px;"> |
||||
<p style="font-size: 14px;">消防救援站: <label style="margin-left: 10px;">{{organizationName}}</label></p> |
||||
</div> |
||||
|
||||
<div class="treeDiv"> |
||||
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl"> |
||||
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding (click)='selectTree(node)'> |
||||
<button type="button" mat-icon-button disabled ></button> |
||||
<li>{{node.name}}</li> |
||||
</mat-tree-node> |
||||
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding (click)='selectTree(node)'> |
||||
<button type="button" mat-icon-button matTreeNodeToggle [attr.aria-label]="'toggle ' + node.name"> |
||||
<mat-icon mat-icon class="mat-icon-rtl-mirror">{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}</mat-icon> |
||||
</button> |
||||
<li>{{node.name}}</li> |
||||
</mat-tree-node> |
||||
</mat-tree> |
||||
</div> |
||||
|
||||
|
||||
<div mat-dialog-content *ngIf="errmsg"> |
||||
<p style="font-size: 14px; color: red;">{{errmsg}}</p> |
||||
</div> |
||||
|
||||
<div mat-dialog-actions> |
||||
<button mat-raised-button color="primary" type="submit" [disabled]="!form.form.valid || toppings.value == null">确定</button> |
||||
<button mat-raised-button color="primary" type="submit" [disabled]="!form.form.valid">确定</button> |
||||
<button mat-raised-button mat-dialog-close>取消</button> |
||||
</div> |
||||
|
||||
|
@ -1,45 +1,44 @@
|
||||
<h2 mat-dialog-title>编辑教员</h2> |
||||
<h2 mat-dialog-title>编辑用户</h2> |
||||
|
||||
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container"> |
||||
|
||||
<div> |
||||
<mat-form-field> |
||||
<input matInput id="idNumber" name="idNumber" |
||||
required [(ngModel)]="IdNumber" placeholder="请输入帐号" autocomplete="off" disabled pattern="^[a-zA-Z][a-zA-Z0-9_]{4,19}$"> |
||||
<input matInput id="name" name="name" [(ngModel)]="name" required readonly placeholder="登录账号" autocomplete="off"> |
||||
</mat-form-field> |
||||
</div> |
||||
|
||||
<div> |
||||
<mat-form-field> |
||||
<input matInput id="realName" name="realName" |
||||
maxlength="100" |
||||
required [(ngModel)]="realName" placeholder="请输入真实姓名" autocomplete="off"> |
||||
<input matInput id="realName" name="realName" [(ngModel)]="realName" required placeholder="用户姓名" autocomplete="off"> |
||||
</mat-form-field> |
||||
</div> |
||||
|
||||
<div> |
||||
<mat-form-field> |
||||
<mat-select placeholder="请选择职务" [formControl]="toppings" multiple required> |
||||
<div style="float: left;"> |
||||
<mat-option *ngFor="let item of detachmentPosts" [value]="item.id">{{item.name}}</mat-option> |
||||
</div> |
||||
<div style="float: left;"> |
||||
<mat-option *ngFor="let item of brigadePosts" [value]="item.id">{{item.name}}</mat-option> |
||||
</div> |
||||
<div style="float: left;"> |
||||
<mat-option *ngFor="let item of RescueStationPosts" [value]="item.id">{{item.name}}</mat-option> |
||||
</div> |
||||
</mat-select> |
||||
</mat-form-field> |
||||
<div style="margin-bottom: 10px;"> |
||||
<p style="font-size: 14px;">消防救援站: <label style="margin-left: 10px;">{{organizationName}}</label></p> |
||||
</div> |
||||
|
||||
<div class="treeDiv"> |
||||
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl"> |
||||
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding (click)='selectTree(node)'> |
||||
<button type="button" mat-icon-button disabled ></button> |
||||
<li>{{node.name}}</li> |
||||
</mat-tree-node> |
||||
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding (click)='selectTree(node)'> |
||||
<button type="button" mat-icon-button matTreeNodeToggle [attr.aria-label]="'toggle ' + node.name"> |
||||
<mat-icon mat-icon class="mat-icon-rtl-mirror">{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}</mat-icon> |
||||
</button> |
||||
<li>{{node.name}}</li> |
||||
</mat-tree-node> |
||||
</mat-tree> |
||||
</div> |
||||
|
||||
<div mat-dialog-content *ngIf="errmsg"> |
||||
<p style="font-size: 14px; color: red;">{{errmsg}}</p> |
||||
</div> |
||||
|
||||
<div mat-dialog-actions> |
||||
<button mat-raised-button color="primary" type="submit" [disabled]="!form.form.valid || toppings.value == null">确定</button> |
||||
<button mat-raised-button color="primary" type="submit" [disabled]="!form.form.valid">确定</button> |
||||
<button mat-raised-button mat-dialog-close>取消</button> |
||||
</div> |
||||
|
||||
|
@ -0,0 +1,179 @@
|
||||
import * as PIXI from 'pixi.js'; |
||||
|
||||
const DEFAULT_LINE_STYLE = { |
||||
width: 1, |
||||
color: 0xffffff, |
||||
alpha: 1, |
||||
alignment: 0.5, |
||||
native: true, |
||||
}; |
||||
|
||||
export class AxGrid extends PIXI.Graphics { |
||||
private _cellSize: number; |
||||
private _correctedWidth: number; |
||||
private _gridWidth: number; |
||||
private _useCorrectedWidth: boolean; |
||||
private _drawBoundaries: any; |
||||
private _amtLines: any; |
||||
|
||||
set cellSize(cellSize) { |
||||
this._cellSize = cellSize || Math.sqrt(this._correctedWidth); |
||||
} |
||||
get cellSize() { |
||||
return this._cellSize; |
||||
} |
||||
get amtLines() { |
||||
return Math.floor(this.gridWidth / this.cellSize); |
||||
} |
||||
get originalWidth() { |
||||
return this._gridWidth; |
||||
} |
||||
/** |
||||
* 修正后的网格宽度,大于最小平方根的数 |
||||
*/ |
||||
get correctedWidth() { |
||||
return this._correctedWidth; |
||||
} |
||||
get useCorrectedWidth() { |
||||
return this._useCorrectedWidth; |
||||
} |
||||
|
||||
/** |
||||
* 网格中每个角落的坐标。 |
||||
*/ |
||||
get bounds() { |
||||
return { |
||||
x1: this.x, |
||||
y1: this.y, |
||||
x2: this.x + this._correctedWidth, |
||||
y2: this.y + this._correctedWidth, |
||||
}; |
||||
} |
||||
|
||||
set drawBoundaries(drawBoundaries) { |
||||
this._drawBoundaries = drawBoundaries; |
||||
} |
||||
|
||||
get drawBoundaries() { |
||||
return this._drawBoundaries; |
||||
} |
||||
|
||||
get gridWidth() { |
||||
if (!this.useCorrectedWidth) { return this._gridWidth; } |
||||
return Math.abs(this.cellSize - Math.sqrt(this._correctedWidth)) <= 1e-6 ? this._correctedWidth : this._gridWidth; |
||||
} |
||||
|
||||
constructor( |
||||
width, |
||||
cellSize= null, |
||||
lineConfig = null, |
||||
useCorrectedWidth = true, |
||||
drawBoundaries = true, |
||||
) { |
||||
super(); |
||||
|
||||
this._cellSize = null; |
||||
this._amtLines = null; |
||||
|
||||
this._gridWidth = width; |
||||
this._useCorrectedWidth = useCorrectedWidth; |
||||
this._correctedWidth = null; |
||||
this._correctWidth(); |
||||
|
||||
this._drawBoundaries = drawBoundaries; |
||||
|
||||
this.cellSize = cellSize; |
||||
|
||||
const lConfig = { ...DEFAULT_LINE_STYLE, ...(lineConfig || {} )}; |
||||
this.lineStyle( |
||||
lConfig.width, |
||||
lConfig.color, |
||||
lConfig.alpha, |
||||
lConfig.alignment, |
||||
lConfig.native |
||||
); |
||||
this.interactive = true; |
||||
this.on('mousemove', (evt) => { |
||||
const mouseCoords = evt.data.getLocalPosition(evt.currentTarget.parent); |
||||
if ( |
||||
mouseCoords.x >= this.bounds.x1 && |
||||
mouseCoords.x <= this.bounds.x2 && |
||||
mouseCoords.y >= this.bounds.y1 && |
||||
mouseCoords.y <= this.bounds.y2 |
||||
) { |
||||
const gridCoords = this.getCellCoordinates(mouseCoords.x, mouseCoords.y); |
||||
this.onMousemove(evt, gridCoords); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 绘制网格 |
||||
*/ |
||||
drawGrid() { |
||||
this.clearGrid(true); |
||||
for (let i = (this._drawBoundaries ? 0 : 1); i <= this.amtLines - (this._drawBoundaries ? 0 : 1); i += 1) { |
||||
const startCoord = i * this._cellSize; |
||||
|
||||
// 画列
|
||||
this.moveTo(startCoord, 0); |
||||
this.lineTo(startCoord, this._correctedWidth); |
||||
|
||||
// 画行
|
||||
this.moveTo(0, startCoord); |
||||
this.lineTo(this._correctedWidth, startCoord); |
||||
} |
||||
this.endFill(); |
||||
|
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 清除网格 |
||||
*/ |
||||
clearGrid(retainLineStyle = true) { |
||||
const { width, alignment, color, alpha, native } = this.line; |
||||
this.clear(); |
||||
|
||||
if (!retainLineStyle) { return; } |
||||
this.lineStyle(width, color, alpha, alignment, native); |
||||
|
||||
return this; |
||||
} |
||||
/** |
||||
* 返回网格的坐标 |
||||
* @param x 坐标x |
||||
* @param y 坐标y |
||||
*/ |
||||
getCellCoordinates(x, y) { |
||||
return { |
||||
x: Math.floor((x - this.bounds.x1) / this.cellSize), |
||||
y: Math.floor((y - this.bounds.y1) / this.cellSize), |
||||
}; |
||||
} |
||||
/** |
||||
* 鼠标移动事件 |
||||
* @param evt 鼠标事件 |
||||
* @param gridCoords 鼠标所在网格坐标 |
||||
*/ |
||||
onMousemove(evt, gridCoords) { |
||||
|
||||
} |
||||
// 默认宽度
|
||||
_correctWidth() { |
||||
if (!this._useCorrectedWidth) { |
||||
this._correctedWidth = this._gridWidth; |
||||
} |
||||
|
||||
this._correctedWidth = Math.ceil(Math.sqrt(this._gridWidth)) ** 2; |
||||
} |
||||
// 自定义宽度
|
||||
correctWidth(width: number) { |
||||
if (!this._useCorrectedWidth) { |
||||
this._correctedWidth = width; |
||||
} |
||||
|
||||
this._correctedWidth = Math.ceil(Math.sqrt(width)) ** 2; |
||||
this.cellSize = null; |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
import { AxRectangleShape } from "./axRectangleShape"; |
||||
|
||||
export class AxImageShapeTest extends AxRectangleShape{ |
||||
/** |
||||
*
|
||||
*/ |
||||
constructor(x:number,y:number,width:number,height:number) { |
||||
super(x,y,width,height); |
||||
|
||||
} |
||||
} |
@ -0,0 +1,90 @@
|
||||
/** |
||||
* 事件系统 |
||||
*/ |
||||
export class AxMessageSystem { |
||||
/** 监听数组 */ |
||||
private static listeners = {}; |
||||
|
||||
/** |
||||
* 注册事件 |
||||
* @param name 事件名称 |
||||
* @param callback 回调函数 |
||||
* @param context 上下文 |
||||
*/ |
||||
public static addListener(name: string, callback: Function, context: any) { |
||||
let observers: Observer[] = AxMessageSystem.listeners[name]; |
||||
if (!observers) { |
||||
AxMessageSystem.listeners[name] = []; |
||||
} |
||||
AxMessageSystem.listeners[name].push(new Observer(callback, context)); |
||||
} |
||||
|
||||
/** |
||||
* 移除事件 |
||||
* @param name 事件名称 |
||||
* @param callback 回调函数 |
||||
* @param context 上下文 |
||||
*/ |
||||
public static removeListener(name: string, callback: Function, context: any) { |
||||
let observers: Observer[] = AxMessageSystem.listeners[name]; |
||||
if (!observers) return; |
||||
let length = observers.length; |
||||
for (let i = 0; i < length; i++) { |
||||
let observer = observers[i]; |
||||
if (observer.compar(context)) { |
||||
observers.splice(i, 1); |
||||
break; |
||||
} |
||||
} |
||||
if (observers.length == 0) { |
||||
delete AxMessageSystem.listeners[name]; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 发送事件 |
||||
* @param name 事件名称 |
||||
*/ |
||||
public static send(name: string, ...args: any[]) { |
||||
let observers: Observer[] = AxMessageSystem.listeners[name]; |
||||
if (!observers) return; |
||||
let length = observers.length; |
||||
for (let i = 0; i < length; i++) { |
||||
let observer = observers[i]; |
||||
observer.notify(name, ...args); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 观察者 |
||||
*/ |
||||
class Observer { |
||||
/** 回调函数 */ |
||||
private callback: Function = null; |
||||
/** 上下文 */ |
||||
private context: any = null; |
||||
|
||||
constructor(callback: Function, context: any) { |
||||
let self = this; |
||||
self.callback = callback; |
||||
self.context = context; |
||||
} |
||||
|
||||
/** |
||||
* 发送通知 |
||||
* @param args 不定参数 |
||||
*/ |
||||
notify(...args: any[]): void { |
||||
let self = this; |
||||
self.callback.call(self.context, ...args); |
||||
} |
||||
|
||||
/** |
||||
* 上下文比较 |
||||
* @param context 上下文 |
||||
*/ |
||||
compar(context: any): boolean { |
||||
return context == this.context; |
||||
} |
||||
} |
@ -0,0 +1,21 @@
|
||||
import { Sprite } from 'pixi.js'; |
||||
import { Graphics } from 'pixi.js'; |
||||
import { WorkingAreaComponent } from '../working-area.component'; |
||||
import { AxShape } from './axShape'; |
||||
|
||||
export class AxRectangleShape extends AxShape { |
||||
/** |
||||
* |
||||
*/ |
||||
constructor(x: number, y: number, width: number, height: number, assetData: any, workingArea: WorkingAreaComponent) { |
||||
super(assetData, workingArea); |
||||
this.beginFill(0x0000ff, 1); |
||||
this.lineStyle(1, 0xff0000, 1); |
||||
this.drawRect(x, y, width, height); |
||||
this.endFill(); |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,64 @@
|
||||
|
||||
/** |
||||
* 选择器 |
||||
*/ |
||||
export class AxSelection { |
||||
constructor() { |
||||
} |
||||
private objects: Set<any> = new Set<any>(); |
||||
// 获得第一个对象
|
||||
public first(): any { |
||||
if (this.objects.size > 0) { |
||||
return [...this.objects][0]; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
// 是否已经选择了对象
|
||||
public has(obj: any): boolean { |
||||
return this.objects.has(obj); |
||||
} |
||||
// 是否所有选择对象都允许编辑
|
||||
public allowEdit(): boolean { |
||||
let allowEdit = true; |
||||
for (const item of this.objects) { |
||||
if (!item.allowEdit) { |
||||
allowEdit = false; |
||||
break; |
||||
} |
||||
} |
||||
return allowEdit; |
||||
} |
||||
// 获得所有对象
|
||||
public all() { |
||||
return [...this.objects]; |
||||
} |
||||
// 获取集合长度
|
||||
public size(): number { |
||||
return this.objects.size; |
||||
} |
||||
// 添加对象
|
||||
public add(obj: any) { |
||||
this.objects.add(obj); |
||||
} |
||||
// 添加集合
|
||||
public addArray(array: any[]) { |
||||
array.forEach(item => { |
||||
this.objects.add(item); |
||||
}); |
||||
} |
||||
// 移除对象
|
||||
public delete(obj: any) { |
||||
this.objects.delete(obj); |
||||
} |
||||
// 移除集合
|
||||
public deleteArray(array: any[]) { |
||||
array.forEach(item => { |
||||
this.objects.delete(item); |
||||
}); |
||||
} |
||||
// 清空所有对象
|
||||
public clear() { |
||||
this.objects.clear(); |
||||
} |
||||
} |
@ -0,0 +1,165 @@
|
||||
import { EventDispatcher } from 'three'; |
||||
import { EVENT_CHANGED } from './events'; |
||||
|
||||
|
||||
// GENERAL:
|
||||
/** The dimensioning unit for 2D floorplan measurements. */ |
||||
export var configDimUnit = 'dimUnit'; |
||||
// WALL:
|
||||
/** The initial wall height in cm. */ |
||||
export const configWallHeight = 'wallHeight'; |
||||
/** The initial wall thickness in cm. */ |
||||
export const configWallThickness = 'wallThickness'; |
||||
|
||||
export const configSystemUI = 'systemUI'; |
||||
|
||||
export const scale = 'scale'; |
||||
|
||||
export const gridSpacing = 'gridSpacing'; |
||||
export const snapToGrid = 'snapToGrid'; |
||||
export const directionalDrag = 'directionalDrag'; |
||||
export const dragOnlyX = 'dragOnlyX'; |
||||
export const dragOnlyY = 'dragOnlyY'; |
||||
export const snapTolerance = 'snapTolerance'; //In CMS
|
||||
export const boundsX = 'boundsX'; //In CMS
|
||||
export const boundsY = 'boundsY'; //In CMS
|
||||
export const viewBounds = 'viewBounds';//In CMS
|
||||
|
||||
export const dimInch = 'inch'; |
||||
|
||||
/** Dimensioning in Inch. */ |
||||
export const dimFeetAndInch = 'feetAndInch'; |
||||
|
||||
/** Dimensioning in Meter. */ |
||||
export const dimMeter = 'm'; |
||||
|
||||
/** Dimensioning in Centi Meter. */ |
||||
export const dimCentiMeter = 'cm'; |
||||
|
||||
/** Dimensioning in Milli Meter. */ |
||||
export const dimMilliMeter = 'mm'; |
||||
|
||||
export const VIEW_TOP = 'topview'; |
||||
export const VIEW_FRONT = 'frontview'; |
||||
export const VIEW_RIGHT = 'rightview'; |
||||
export const VIEW_LEFT = 'leftview'; |
||||
export const VIEW_ISOMETRY = 'isometryview'; |
||||
|
||||
export enum WallTypes { |
||||
STRAIGHT, |
||||
CURVED |
||||
} |
||||
|
||||
export const TEXTURE_DEFAULT_REPEAT = 300; |
||||
export const defaultWallTexture = |
||||
{ |
||||
color: '#FFFFFF', repeat: TEXTURE_DEFAULT_REPEAT, normalmap: 'textures/Wall/Brick_Wall_017_SD/Brick_Wall_017_normal.jpg', roughnessmap: 'textures/Wall/Brick_Wall_017_SD/Brick_Wall_017_roughness.jpg', colormap: 'textures/Wall/Brick_Wall_017_SD/Brick_Wall_017_basecolor.jpg', ambientmap: 'textures/Wall/Brick_Wall_017_SD/Brick_Wall_017_ambientOcclusion.jpg', bumpmap: 'textures/Wall/Brick_Wall_017_SD/Brick_Wall_017_height.png' |
||||
}; |
||||
export const defaultFloorTexture = |
||||
{ |
||||
color: '#FFFFFF', emissive: '#181818', repeat: TEXTURE_DEFAULT_REPEAT, ambientmap: 'textures/Floor/Marble_Tiles_001/Marble_Tiles_001_ambientOcclusion.jpg', colormap: 'textures/Floor/Marble_Tiles_001/Marble_Tiles_001_basecolor.jpg', roughnessmap: 'textures/Floor/Marble_Tiles_001/Marble_Tiles_001_roughness.jpg', normalmap: 'textures/Floor/Marble_Tiles_001/Marble_Tiles_001_normal.jpg' |
||||
}; |
||||
|
||||
export const TEXTURE_PROPERTY_COLOR = 'color'; |
||||
export const TEXTURE_NO_PREVIEW = 'textures/NoPreview.jpg'; |
||||
|
||||
export var config = { |
||||
dimUnit: dimCentiMeter, |
||||
wallHeight: 250, |
||||
wallThickness: 20, |
||||
systemUI: false, |
||||
scale: 1, |
||||
snapToGrid: true, |
||||
dragOnlyX: false, |
||||
dragOnlyY: false, |
||||
snapTolerance: 50, |
||||
gridSpacing: 20, // 50,
|
||||
directionalDrag: true, |
||||
boundsX: 500, |
||||
boundsY: 500, |
||||
viewBounds: 60000 |
||||
}; |
||||
|
||||
export var wallInformation = { exterior: false, interior: false, midline: true, labels: true, exteriorlabel: 'e:', interiorlabel: 'i:', midlinelabel: 'm:' }; |
||||
|
||||
|
||||
/** |
||||
* The tolerance in cms between corners, otherwise below this tolerance they will snap together as one corner*/ |
||||
export const cornerTolerance = 20; |
||||
|
||||
/** Global configuration to customize the whole system. |
||||
* This is a singleton instance; |
||||
*/ |
||||
export class Configuration extends EventDispatcher { |
||||
private static instance = new Configuration(); |
||||
constructor() { |
||||
/** Configuration data loaded from/stored to extern. */ |
||||
// this.data = {dimUnit: dimCentiMeter, wallHeight: 250, wallThickness: 10};
|
||||
super(); |
||||
} |
||||
|
||||
static getInstance() { |
||||
if (this.instance === undefined |
||||
|| this.instance === null) { |
||||
this.instance = new Configuration(); |
||||
} |
||||
return this.instance; |
||||
} |
||||
|
||||
static getData() { |
||||
// return {dimUnit: dimCentiMeter,wallHeight: 250, wallThickness: 10};
|
||||
return config; |
||||
} |
||||
|
||||
/** Set a configuration parameter. */ |
||||
static setValue(key, value) { |
||||
// this.data[key] = value;
|
||||
config[key] = value; |
||||
// if(key !== viewBounds){
|
||||
Configuration.getInstance().dispatchEvent({ type: EVENT_CHANGED, item: Configuration.getInstance(), 'key': key, 'value': value }); |
||||
// }
|
||||
} |
||||
|
||||
/** Get a string configuration parameter. */ |
||||
static getStringValue(key) { |
||||
switch (key) { |
||||
case configDimUnit: |
||||
// return String(this.data[key]);
|
||||
return String(Configuration.getData()[key]); |
||||
default: |
||||
throw new Error('Invalid string configuration parameter: ' + key); |
||||
} |
||||
} |
||||
|
||||
/** Get a numeric configuration parameter. */ |
||||
static getNumericValue(key) { |
||||
switch (key) { |
||||
case configSystemUI: |
||||
case configWallHeight: |
||||
case configWallThickness: |
||||
case scale: |
||||
case snapTolerance: |
||||
case gridSpacing: |
||||
case boundsX: |
||||
case boundsY: |
||||
case viewBounds: |
||||
// return Number(this.data[key]);
|
||||
return Number(Configuration.getData()[key]); |
||||
default: |
||||
throw new Error('Invalid numeric configuration parameter: ' + key); |
||||
} |
||||
} |
||||
|
||||
/** Get a numeric configuration parameter. */ |
||||
static getBooleanValue(key) { |
||||
switch (key) { |
||||
case snapToGrid: |
||||
case directionalDrag: |
||||
case dragOnlyX: |
||||
case dragOnlyY: |
||||
return Boolean(Configuration.getData()[key]); |
||||
default: |
||||
throw new Error('Invalid Boolean configuration parameter: ' + key); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,145 @@
|
||||
import { Vector2, Vector3 } from 'three'; |
||||
import { Configuration, configDimUnit,dimInch, dimFeetAndInch, dimMeter, dimCentiMeter, dimMilliMeter } from './configuration'; |
||||
|
||||
export const decimals = 1000; |
||||
|
||||
export const cmPerFoot = 30.48; |
||||
export const pixelsPerFoot = 5.0; |
||||
|
||||
export const pixelsPerCm = 1; // 0.5;
|
||||
export const cmPerPixel = (1.0 / pixelsPerCm); |
||||
|
||||
|
||||
export const dimensioningOptions = [dimInch, dimFeetAndInch, dimMeter, dimCentiMeter, dimMilliMeter]; |
||||
|
||||
|
||||
/** Dimensioning functions. */ |
||||
export class Dimensioning { |
||||
static cmToPixelVector2D(cmV2d) { |
||||
let pixelV2d = new Vector2(Dimensioning.cmToPixel(cmV2d.x), Dimensioning.cmToPixel(cmV2d.y)); |
||||
return pixelV2d; |
||||
} |
||||
|
||||
static cmToPixelVector3D(cmV3d) { |
||||
let pixelV2d = new Vector3(Dimensioning.cmToPixel(cmV3d.x), Dimensioning.cmToPixel(cmV3d.y), Dimensioning.cmToPixel(cmV3d.z)); |
||||
return pixelV2d; |
||||
} |
||||
|
||||
static pixelToCmVector2D(pixelV2d) { |
||||
let cmV2d = new Vector2(Dimensioning.cmToPixel(pixelV2d.x), Dimensioning.cmToPixel(pixelV2d.y)); |
||||
return cmV2d; |
||||
} |
||||
|
||||
static pixelToCmVector3D(pixel3d) { |
||||
let cmV2d = new Vector3(Dimensioning.cmToPixel(pixel3d.x), Dimensioning.cmToPixel(pixel3d.y), Dimensioning.cmToPixel(pixel3d.z)); |
||||
return cmV2d; |
||||
} |
||||
|
||||
static cmToPixel(cm, apply_scale = true) { |
||||
if (apply_scale) { |
||||
return cm * pixelsPerCm * Configuration.getNumericValue('scale'); |
||||
} |
||||
return cm * pixelsPerCm; |
||||
} |
||||
|
||||
static pixelToCm(pixel, apply_scale = true) { |
||||
if (apply_scale) { |
||||
return pixel * cmPerPixel * (1.0 / Configuration.getNumericValue('scale')); |
||||
} |
||||
return pixel * cmPerPixel; |
||||
} |
||||
|
||||
static roundOff(value, decimals) { |
||||
return Math.round(decimals * value) / decimals; |
||||
} |
||||
/** Converts cm to dimensioning number. |
||||
* @param cm Centi meter value to be converted. |
||||
* @returns Number representation. |
||||
*/ |
||||
static cmFromMeasureRaw(measure) { |
||||
switch (Configuration.getStringValue(configDimUnit)) { |
||||
case dimFeetAndInch: |
||||
return Math.round(decimals * (measure * 30.480016459203095991)) / decimals; |
||||
case dimInch: |
||||
return Math.round(decimals * (measure * 2.5400013716002578512)) / decimals; |
||||
case dimMilliMeter: |
||||
return Math.round(decimals * (measure * 0.10000005400001014955)) / decimals; |
||||
case dimCentiMeter: |
||||
return measure; |
||||
case dimMeter: |
||||
default: |
||||
return Math.round(decimals * 100 * measure) / decimals; |
||||
} |
||||
} |
||||
|
||||
/** Converts cm to dimensioning string. |
||||
* @param cm Centi meter value to be converted. |
||||
* @returns String representation. |
||||
*/ |
||||
static cmFromMeasure(measure) { |
||||
switch (Configuration.getStringValue(configDimUnit)) { |
||||
case dimFeetAndInch: |
||||
return Math.round(decimals * (measure * 30.480016459203095991)) / decimals + 'cm'; |
||||
case dimInch: |
||||
return Math.round(decimals * (measure * 2.5400013716002578512)) / decimals + 'cm'; |
||||
case dimMilliMeter: |
||||
return Math.round(decimals * (measure * 0.10000005400001014955)) / decimals + 'cm'; |
||||
case dimCentiMeter: |
||||
return measure; |
||||
case dimMeter: |
||||
default: |
||||
return Math.round(decimals * 100 * measure) / decimals + 'cm'; |
||||
} |
||||
} |
||||
|
||||
/** Converts cm to dimensioning string. |
||||
* @param cm Centi meter value to be converted. |
||||
* @returns String representation. |
||||
*/ |
||||
static cmToMeasureRaw(cm, power = 1) { |
||||
switch (Configuration.getStringValue(configDimUnit)) { |
||||
case dimFeetAndInch: // dimFeetAndInch returns only the feet
|
||||
var allInFeet = (cm * Math.pow(0.032808416666669996953, power)); |
||||
return allInFeet; |
||||
case dimInch: |
||||
var inches = Math.round(decimals * (cm * Math.pow(0.393700, power))) / decimals; |
||||
return inches; |
||||
case dimMilliMeter: |
||||
var mm = Math.round(decimals * (cm * Math.pow(10, power))) / decimals; |
||||
return mm; |
||||
case dimCentiMeter: |
||||
return Math.round(decimals * cm) / decimals; |
||||
case dimMeter: |
||||
default: |
||||
var m = Math.round(decimals * (cm * Math.pow(0.01, power))) / decimals; |
||||
return m; |
||||
} |
||||
} |
||||
|
||||
/** Converts cm to dimensioning string. |
||||
* @param cm Centi meter value to be converted. |
||||
* @returns String representation. |
||||
*/ |
||||
static cmToMeasure(cm, power = 1) { |
||||
switch (Configuration.getStringValue(configDimUnit)) { |
||||
case dimFeetAndInch: |
||||
var allInFeet = (cm * Math.pow(0.032808416666669996953, power)); |
||||
var floorFeet = Math.floor(allInFeet); |
||||
var remainingFeet = allInFeet - floorFeet; |
||||
var remainingInches = Math.round(remainingFeet * 12); |
||||
return floorFeet + '\'' + remainingInches + ''; |
||||
case dimInch: |
||||
var inches = Math.round(decimals * (cm * Math.pow(0.393700, power))) / decimals; |
||||
return inches + '\''; |
||||
case dimMilliMeter: |
||||
var mm = Math.round(decimals * (cm * Math.pow(10, power))) / decimals; |
||||
return '' + mm + 'mm'; |
||||
case dimCentiMeter: |
||||
return '' + Math.round(decimals * cm) / decimals + 'cm'; |
||||
case dimMeter: |
||||
default: |
||||
var m = Math.round(decimals * (cm * Math.pow(0.01, power))) / decimals; |
||||
return '' + m + 'm'; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,71 @@
|
||||
export const EVENT_ACTION = 'ACTION_EVENT'; |
||||
export const EVENT_DELETED = 'DELETED_EVENT'; |
||||
export const EVENT_MOVED = 'MOVED_EVENT'; |
||||
export const EVENT_REDRAW = 'REDRAW_EVENT'; |
||||
export const EVENT_NEW = 'NEW_EVENT'; |
||||
export const EVENT_LOADED = 'LOADED_EVENT'; |
||||
export const EVENT_LOADING = 'LOADING_EVENT'; |
||||
export const EVENT_UPDATED = 'UPDATED_EVENT'; |
||||
export const EVENT_SAVED = 'SAVED_EVENT'; |
||||
export const EVENT_CHANGED = 'CHANGED_EVENT'; |
||||
export const EVENT_GLTF_READY = 'GLTF_READY_EVENT'; |
||||
|
||||
export const EVENT_EXTERNAL_FLOORPLAN_LOADED = 'EXTERNAL_FLOORPLAN_LOADED_EVENT'; |
||||
|
||||
export const EVENT_NEW_PARAMETRIC_ITEM = 'NEW_PARAMETRIC_ITEM_EVENT'; |
||||
export const EVENT_NEW_ITEM = 'NEW_ITEM_EVENT'; |
||||
export const EVENT_ITEM_LOADING = 'ITEM_LOADING_EVENT'; |
||||
export const EVENT_ITEM_LOADED = 'ITEM_LOADED_EVENT'; |
||||
export const EVENT_ITEM_REMOVED = 'ITEM_REMOVED_EVENT'; |
||||
|
||||
export const EVENT_ITEM_SELECTED = 'ITEM_SELECTED_EVENT'; |
||||
export const EVENT_ITEM_MOVE = 'ITEM_MOVED_EVENT'; |
||||
export const EVENT_ITEM_MOVE_FINISH = 'ITEM_MOVED_FINISH_EVENT'; |
||||
export const EVENT_ITEM_HOVERON = 'ITEM_HOVERON_EVENT'; |
||||
export const EVENT_ITEM_HOVEROFF = 'ITEM_HOVEROFF_EVENT'; |
||||
export const EVENT_NO_ITEM_SELECTED = 'ITEM_NO_SELECTED_EVENT'; |
||||
|
||||
export const EVENT_MODE_RESET = 'MODE_RESET_EVENT'; |
||||
export const EVENT_CAMERA_MOVED = 'CAMERA_MOVED_EVENT'; |
||||
export const EVENT_CAMERA_ACTIVE_STATUS = 'CAMERA_ACTIVE_STATUS_EVENT'; |
||||
export const EVENT_CAMERA_VIEW_CHANGE = 'CAMERA_VIEW_CHANGE_EVENT'; |
||||
export const EVENT_FPS_EXIT = 'CAMERA_FPS_EXIT_EVENT'; |
||||
|
||||
export const EVENT_WALL_CLICKED = 'WALL_CLICKED_EVENT'; |
||||
export const EVENT_ROOM_CLICKED = 'ROOM_CLICKED_EVENT'; |
||||
export const EVENT_FLOOR_CLICKED = 'FLOOR_CLICKED_EVENT'; |
||||
export const EVENT_NOTHING_CLICKED = 'NOTHING_CLICKED_EVENT'; |
||||
|
||||
export const EVENT_ROOM_NAME_CHANGED = 'CHANGED_ROOM_NAME_EVENT'; |
||||
export const EVENT_NEW_ROOMS_ADDED = 'ADDED_NEW_ROOMS_EVENT'; |
||||
|
||||
export const EVENT_CORNER_ATTRIBUTES_CHANGED = 'CORNER_ATTRIBUTES_CHANGED_EVENT'; |
||||
export const EVENT_WALL_ATTRIBUTES_CHANGED = 'WALL_ATTRIBUTES_CHANGED_EVENT'; |
||||
export const EVENT_ROOM_ATTRIBUTES_CHANGED = 'ROOM_ATTRIBUTES_CHANGED_EVENT'; |
||||
|
||||
export const EVENT_CORNER_2D_CLICKED = 'CORNER_CLICKED_2D_EVENT'; |
||||
export const EVENT_WALL_2D_CLICKED = 'WALL_CLICKED_2D_EVENT'; |
||||
export const EVENT_ROOM_2D_CLICKED = 'ROOM_CLICKED_2D_EVENT'; |
||||
export const EVENT_2D_UNSELECTED = 'UNSELECTED_2D_EVENT'; |
||||
export const EVENT_2D_SELECTED = 'SELECTED_2D_EVENT'; |
||||
export const EVENT_NOTHING_2D_SELECTED = 'NOTHING_2D_SELECTED_EVENT'; |
||||
|
||||
export const EVENT_CORNER_2D_DOUBLE_CLICKED = 'CORNER_DOUBLE_CLICKED_2D_EVENT'; |
||||
export const EVENT_WALL_2D_DOUBLE_CLICKED = 'WALL_DOUBLE_CLICKED_2D_EVENT'; |
||||
export const EVENT_ROOM_2D_DOUBLE_CLICKED = 'ROOM_DOUBLE_CLICKED_2D_EVENT'; |
||||
|
||||
export const EVENT_CORNER_2D_HOVER = 'CORNER_HOVER_2D_EVENT'; |
||||
export const EVENT_WALL_2D_HOVER = 'WALL_HOVER_2D_EVENT'; |
||||
export const EVENT_ROOM_2D_HOVER = 'ROOM_HOVER_2D_EVENT'; |
||||
|
||||
export const EVENT_KEY_PRESSED = 'KEY_PRESSED_EVENT'; |
||||
export const EVENT_KEY_RELEASED = 'KEY_RELEASED_EVENT'; |
||||
|
||||
export const EVENT_UPDATE_TEXTURES = 'UPDATE_TEXTURES_EVENT'; |
||||
export const EVENT_MODIFY_TEXTURE_ATTRIBUTE = 'MODIFY_TEXTURE_ATTRIBUTE_EVENT'; |
||||
|
||||
export const EVENT_PARAMETRIC_GEOMETRY_UPATED = 'PARAMETRIC_GEOMETRY_UPATED_EVENT'; |
||||
|
||||
export const EVENT_SELECTION_CHANGED = 'selectionChanged'; |
||||
|
||||
export const EVENT_IMAGE_RESIZE = 'imageResize'; |
@ -0,0 +1,87 @@
|
||||
import { Configuration, gridSpacing, viewBounds } from './configuration'; |
||||
import { EVENT_CHANGED } from './events'; |
||||
import { Graphics } from 'pixi.js'; |
||||
import { Vector2 } from 'three'; |
||||
import { Dimensioning } from './dimensioning'; |
||||
|
||||
const GRID_SIZE = 10000; |
||||
|
||||
export class Grid2D extends Graphics { |
||||
|
||||
canvas; |
||||
options; |
||||
size; |
||||
gridScale; |
||||
constructor(canvas, options) { |
||||
super(); |
||||
// this.drawRect(0, 0, GRID_SIZE, GRID_SIZE);
|
||||
this.canvas = canvas; |
||||
this.options = options; |
||||
this.size = new Vector2(GRID_SIZE, GRID_SIZE); |
||||
this.gridScale = 1.0; |
||||
this.width = this.size.x; |
||||
this.height = this.size.y; |
||||
this.drawRect(0, 0, GRID_SIZE, GRID_SIZE); |
||||
this.pivot.x = this.pivot.y = 0.5; |
||||
Configuration.getInstance().addEventListener(EVENT_CHANGED, (evt) => this.updateGrid()); |
||||
this.updateGrid(); |
||||
} |
||||
|
||||
updateGrid() { |
||||
let gridSize = Dimensioning.cmToPixel(Configuration.getNumericValue(viewBounds) * 1); |
||||
let spacingCMS = Configuration.getNumericValue(gridSpacing); |
||||
let spacing = Dimensioning.cmToPixel(spacingCMS); |
||||
let totalLines = gridSize / spacing; |
||||
let halfSize = gridSize * 0.5; |
||||
let linewidth = Math.max(1.0 / this.gridScale, 1.0) * 1 / this.canvas.scale.x;// 增加缩放系数
|
||||
let highlightLineWidth = Math.max(1 / this.gridScale, 1.0) * 1 / this.canvas.scale.x;// 增加缩放系数
|
||||
let normalColor = 0xE0E0E0; |
||||
let highlightColor = 0xD0D0D0; |
||||
const cellSize = 5; |
||||
this.clear(); |
||||
for (let i = 0; i <= totalLines; i++) { |
||||
let co = (i * spacing) - halfSize; |
||||
if (i % cellSize === 0) { |
||||
this.lineStyle(highlightLineWidth, highlightColor).moveTo(-halfSize, co).lineTo(halfSize, co); |
||||
this.lineStyle(highlightLineWidth, highlightColor).moveTo(co, -halfSize).lineTo(co, halfSize); |
||||
} else { |
||||
this.lineStyle(linewidth, normalColor).moveTo(-halfSize, co).lineTo(halfSize, co); |
||||
this.lineStyle(linewidth, normalColor).moveTo(co, -halfSize).lineTo(co, halfSize); |
||||
} |
||||
} |
||||
this.endFill(); |
||||
|
||||
this.beginFill(0xFF0000, 1.0); |
||||
this.drawCircle(-halfSize, -halfSize, 5); |
||||
this.drawCircle(halfSize, -halfSize, 5); |
||||
this.drawCircle(halfSize, halfSize, 5); |
||||
this.drawCircle(-halfSize, halfSize, 5); |
||||
this.drawCircle(0, 0, 5); |
||||
this.endFill(); |
||||
} |
||||
|
||||
getGridScale() { |
||||
return this.gridScale; |
||||
} |
||||
|
||||
setGridScale(value) { |
||||
this.gridScale = value; |
||||
this.updateGrid(); |
||||
} |
||||
|
||||
configurationUpdate(evt) { |
||||
if (evt.key === gridSpacing) { |
||||
this.updateGrid(); |
||||
} |
||||
} |
||||
getCellCoordinates(x, y) { |
||||
let gridSize = Dimensioning.cmToPixel(Configuration.getNumericValue(viewBounds) * 1); |
||||
let spacingCMS = Configuration.getNumericValue(gridSpacing); |
||||
let spacing = Dimensioning.cmToPixel(spacingCMS); |
||||
let halfSize = gridSize * 0.5; |
||||
return { |
||||
x: Math.floor((x - -halfSize) / spacing), |
||||
y: Math.floor((y - -halfSize) / spacing), |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,37 @@
|
||||
class MyEvent<T> extends CustomEvent<T> {
|
||||
public static readonly CMD: string = "EVENT_NAME"; |
||||
public constructor($type: string , $data: T ) {
|
||||
super( $type , { detail: $data, bubbles: true, cancelable: true, composed: true }); |
||||
} |
||||
} |
||||
|
||||
class MyDispatch extends EventTarget {
|
||||
private static _instance: MyDispatch; |
||||
public static get Instance(): MyDispatch {
|
||||
if (!MyDispatch._instance) MyDispatch._instance = new MyDispatch(); |
||||
return MyDispatch._instance; |
||||
} |
||||
public send<T>($data: T, $type: string = MyEvent.CMD): void {
|
||||
const $event: CustomEvent = new MyEvent<T>($type, $data); |
||||
this.dispatchEvent($event); |
||||
} |
||||
} |
||||
|
||||
class Test {
|
||||
|
||||
public constructor() {
|
||||
MyDispatch.Instance.addEventListener(MyEvent.CMD, this.onEvent as EventListener); |
||||
} |
||||
private onEvent($e: MyEvent<ITest>): void {
|
||||
console.log(`target ${$e.target}`); |
||||
console.log(`name: ${$e.detail._name} , occupation: ${$e.detail._occupation}`); |
||||
} |
||||
} |
||||
|
||||
interface ITest {
|
||||
_name: string; |
||||
_occupation: string; |
||||
} |
||||
|
||||
let $test: Test = new Test(); |
||||
MyDispatch.Instance.send<ITest>({ _name: `Aonaufly`, _occupation: `it` }); |
@ -1,2 +1 @@
|
||||
<div #content style="width:100%;height:100%;" (mousewheel)='this.mouseWheelHandel($event)' |
||||
(DOMMouseScroll)='this.mouseWheelHandel($event)'></div> |
||||
<div #content style="width:100%;height:100%;"></div> |
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 939 B |
Loading…
Reference in new issue