Merge branch 'master' of git.code.tencent.com:xian-ncc-da/xian-ncc-da-client
This commit is contained in:
commit
19166ae146
@ -3,7 +3,7 @@
|
||||
<q-input outlined readonly v-model="runLineModel.id" label="id" hint="" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="runLineModel.code"
|
||||
v-model="runLineModel.code"
|
||||
@blur="onUpdate"
|
||||
label="名称"
|
||||
/>
|
||||
@ -55,6 +55,12 @@
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-btn
|
||||
color="primary"
|
||||
style="margin: auto"
|
||||
@click="generatePathLine"
|
||||
label="生成轨迹线"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
@ -63,6 +69,7 @@ import { RunLineData } from 'src/drawApp/graphics/RunLineInteraction';
|
||||
import { RunLine } from 'src/graphics/runLine/RunLine';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, watch } from 'vue';
|
||||
import { Point } from 'pixi.js';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const runLineModel = reactive(new RunLineData());
|
||||
@ -90,4 +97,17 @@ function onUpdate() {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(runLine, runLineModel);
|
||||
}
|
||||
}
|
||||
function generatePathLine() {
|
||||
const runLine = drawStore.selectedGraphic as RunLine;
|
||||
if (runLine) {
|
||||
const points = runLineModel.points;
|
||||
const pointsUp: Point[] = [];
|
||||
const pointsDown: Point[] = [];
|
||||
points.forEach((item) => {
|
||||
pointsUp.push(new Point(item.x, item.y - 10));
|
||||
pointsDown.push(new Point(item.x, item.y + 10));
|
||||
});
|
||||
runLine.generatePathLine(pointsUp, pointsDown);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
47
src/drawApp/graphics/PathLineInteraction.ts
Normal file
47
src/drawApp/graphics/PathLineInteraction.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { IPointData } from 'pixi.js';
|
||||
import { IPathLineData } from 'src/graphics/pathLine/PathLine';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
|
||||
export class PathLineData extends GraphicDataBase implements IPathLineData {
|
||||
constructor(data?: graphicData.PathLine) {
|
||||
let pathLine;
|
||||
if (!data) {
|
||||
pathLine = new graphicData.PathLine({
|
||||
common: GraphicDataBase.defaultCommonInfo(),
|
||||
});
|
||||
} else {
|
||||
pathLine = data;
|
||||
}
|
||||
super(pathLine);
|
||||
}
|
||||
|
||||
public get data(): graphicData.PathLine {
|
||||
return this.getData<graphicData.PathLine>();
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get points(): IPointData[] {
|
||||
return this.data.points;
|
||||
}
|
||||
set points(points: IPointData[]) {
|
||||
this.data.points = points.map(
|
||||
(p) => new graphicData.Point({ x: p.x, y: p.y })
|
||||
);
|
||||
}
|
||||
clone(): PathLineData {
|
||||
return new PathLineData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: PathLineData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: PathLineData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
61
src/drawApp/graphics/PolygonInteraction.ts
Normal file
61
src/drawApp/graphics/PolygonInteraction.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { IPolygonData } from 'src/graphics/polygon/Polygon';
|
||||
import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
import { IPointData } from 'pixi.js';
|
||||
|
||||
export class PolygonData extends GraphicDataBase implements IPolygonData {
|
||||
constructor(data?: graphicData.Polygon) {
|
||||
let Polygon;
|
||||
if (!data) {
|
||||
Polygon = new graphicData.Polygon({
|
||||
common: GraphicDataBase.defaultCommonInfo(),
|
||||
});
|
||||
} else {
|
||||
Polygon = data;
|
||||
}
|
||||
super(Polygon);
|
||||
}
|
||||
|
||||
public get data(): graphicData.Polygon {
|
||||
return this.getData<graphicData.Polygon>();
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this.data.code;
|
||||
}
|
||||
set code(v: string) {
|
||||
this.data.code = v;
|
||||
}
|
||||
get lineWidth(): number {
|
||||
return this.data.lineWidth;
|
||||
}
|
||||
set lineWidth(v: number) {
|
||||
this.data.lineWidth = v;
|
||||
}
|
||||
get lineColor(): string {
|
||||
return this.data.lineColor;
|
||||
}
|
||||
set lineColor(v: string) {
|
||||
this.data.lineColor = v;
|
||||
}
|
||||
get points(): IPointData[] {
|
||||
return this.data.points;
|
||||
}
|
||||
set points(points: IPointData[]) {
|
||||
this.data.points = points.map(
|
||||
(p) => new graphicData.Point({ x: p.x, y: p.y })
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
clone(): PolygonData {
|
||||
return new PolygonData(this.data.cloneMessage());
|
||||
}
|
||||
copyFrom(data: PolygonData): void {
|
||||
pb_1.Message.copyInto(data.data, this.data);
|
||||
}
|
||||
eq(other: PolygonData): boolean {
|
||||
return pb_1.Message.equals(this.data, other.data);
|
||||
}
|
||||
}
|
@ -46,6 +46,18 @@ export class RunLineData extends GraphicDataBase implements IRunLineData {
|
||||
set nameBgColor(v: string) {
|
||||
this.data.nameBgColor = v;
|
||||
}
|
||||
get upPathLineId(): string {
|
||||
return this.data.upPathLineId;
|
||||
}
|
||||
set upPathLineId(v: string) {
|
||||
this.data.upPathLineId = v;
|
||||
}
|
||||
get downPathLineId(): string {
|
||||
return this.data.downPathLineId;
|
||||
}
|
||||
set downPathLineId(v: string) {
|
||||
this.data.downPathLineId = v;
|
||||
}
|
||||
clone(): RunLineData {
|
||||
return new RunLineData(this.data.cloneMessage());
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ import { graphicData } from 'src/protos/stationLayoutGraphics';
|
||||
import { Rect } from 'src/graphics/rect/Rect';
|
||||
import { RectDraw } from 'src/graphics/rect/RectDrawAssistant';
|
||||
import { RectData } from './graphics/RectInteraction';
|
||||
import { Polygon } from 'src/graphics/polygon/Polygon';
|
||||
import { PolygonDraw } from 'src/graphics/polygon/PolygonDrawAssistant';
|
||||
import { PolygonData } from './graphics/PolygonInteraction';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import { PlatformData } from './graphics/PlatformInteraction';
|
||||
import { PlatformDraw } from 'src/graphics/platform/PlatformDrawAssistant';
|
||||
@ -49,6 +52,9 @@ import { successNotify, errorNotify } from '../utils/CommonNotify';
|
||||
import { Section } from 'src/graphics/section/Section';
|
||||
import { SectionDraw } from 'src/graphics/section/SectionDrawAssistant';
|
||||
import { SectionData } from './graphics/SectionInteraction';
|
||||
import { PathLine } from 'src/graphics/pathLine/PathLine';
|
||||
import { PathLineDraw } from 'src/graphics/pathLine/PathLineDrawAssistant';
|
||||
import { PathLineData } from './graphics/PathLineInteraction';
|
||||
|
||||
export function fromStoragePoint(p: graphicData.Point): Point {
|
||||
return new Point(p.x, p.y);
|
||||
@ -130,6 +136,8 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
|
||||
| StationLineDraw
|
||||
| RectDraw
|
||||
| TrainLineDraw
|
||||
| PolygonDraw
|
||||
| PathLineDraw
|
||||
)[] = [];
|
||||
if (draftType === 'Line') {
|
||||
drawAssistants = [
|
||||
@ -149,6 +157,9 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
|
||||
// return new TrainData();
|
||||
// }),
|
||||
new SectionDraw(app, () => new SectionData()),
|
||||
/* new PolygonDraw(app, () => {
|
||||
return new PolygonData();
|
||||
}), */
|
||||
];
|
||||
} else {
|
||||
drawAssistants = [
|
||||
@ -164,6 +175,9 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
|
||||
new TrainLineDraw(app, () => {
|
||||
return new TrainLineData();
|
||||
}),
|
||||
new PathLineDraw(app, () => {
|
||||
return new PathLineData();
|
||||
}),
|
||||
];
|
||||
app.addKeyboardListener(
|
||||
new KeyListener({
|
||||
@ -275,6 +289,9 @@ export function saveDrawDatas(app: JlDrawApp) {
|
||||
} else if (TrainLine.Type === g.type) {
|
||||
const trainLineData = (g as TrainLine).saveData();
|
||||
storage.trainLines.push((trainLineData as TrainLineData).data);
|
||||
} else if (PathLine.Type === g.type) {
|
||||
const pathLineData = (g as PathLine).saveData();
|
||||
storage.pathLines.push((pathLineData as PathLineData).data);
|
||||
}
|
||||
});
|
||||
const base64 = fromUint8Array(storage.serialize());
|
||||
@ -336,6 +353,9 @@ export async function loadDrawDatas(app: GraphicApp) {
|
||||
storage.trainLines.forEach((trainLine) => {
|
||||
datas.push(new TrainLineData(trainLine));
|
||||
});
|
||||
storage.pathLines.forEach((pathLine) => {
|
||||
datas.push(new PathLineData(pathLine));
|
||||
});
|
||||
app.loadGraphic(datas);
|
||||
} else {
|
||||
app.loadGraphic([]);
|
||||
|
74
src/graphics/pathLine/PathLine.ts
Normal file
74
src/graphics/pathLine/PathLine.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { JlGraphic, GraphicData, JlGraphicTemplate } from 'src/jl-graphic';
|
||||
import { Graphics, IPointData } from 'pixi.js';
|
||||
|
||||
export interface IPathLineData extends GraphicData {
|
||||
get code(): string;
|
||||
set code(v: string);
|
||||
get points(): IPointData[]; // 线坐标点
|
||||
set points(points: IPointData[]);
|
||||
clone(): IPathLineData;
|
||||
copyFrom(data: IPathLineData): void;
|
||||
eq(other: IPathLineData): boolean;
|
||||
}
|
||||
|
||||
export const pathLineConsts = {
|
||||
pathLineWidth: 1,
|
||||
pathLineColor: '0X000000',
|
||||
};
|
||||
|
||||
export class PathLine extends JlGraphic {
|
||||
static Type = 'PathLine';
|
||||
pathLine: Graphics = new Graphics();
|
||||
constructor() {
|
||||
super(PathLine.Type);
|
||||
this.addChild(this.pathLine);
|
||||
}
|
||||
|
||||
get datas(): IPathLineData {
|
||||
return this.getDatas<IPathLineData>();
|
||||
}
|
||||
doRepaint(): void {
|
||||
if (this.datas.points.length < 2) {
|
||||
throw new Error('RunLine坐标数据异常');
|
||||
}
|
||||
this.pathLine.clear();
|
||||
this.pathLine.lineStyle({
|
||||
width: pathLineConsts.pathLineWidth,
|
||||
color: pathLineConsts.pathLineColor,
|
||||
});
|
||||
const start = this.getStartPoint();
|
||||
this.pathLine.moveTo(start.x, start.y);
|
||||
for (let i = 0; i < this.datas.points.length; i++) {
|
||||
const p = this.datas.points[i];
|
||||
this.pathLine.lineTo(p.x, p.y);
|
||||
}
|
||||
}
|
||||
|
||||
get linePoints(): IPointData[] {
|
||||
return this.datas.points;
|
||||
}
|
||||
set linePoints(points: IPointData[]) {
|
||||
const old = this.datas.clone();
|
||||
old.points = points;
|
||||
this.updateData(old);
|
||||
}
|
||||
getStartPoint(): IPointData {
|
||||
return this.datas.points[0];
|
||||
}
|
||||
getEndPoint(): IPointData {
|
||||
return this.datas.points[this.datas.points.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
export class PathLineTemplate extends JlGraphicTemplate<PathLine> {
|
||||
pathLineColor: string;
|
||||
pathLineWidth: number;
|
||||
constructor() {
|
||||
super(PathLine.Type);
|
||||
this.pathLineColor = pathLineConsts.pathLineColor;
|
||||
this.pathLineWidth = pathLineConsts.pathLineWidth;
|
||||
}
|
||||
new(): PathLine {
|
||||
return new PathLine();
|
||||
}
|
||||
}
|
184
src/graphics/pathLine/PathLineDrawAssistant.ts
Normal file
184
src/graphics/pathLine/PathLineDrawAssistant.ts
Normal file
@ -0,0 +1,184 @@
|
||||
import {
|
||||
GraphicDrawAssistant,
|
||||
JlDrawApp,
|
||||
JlGraphic,
|
||||
GraphicInteractionPlugin,
|
||||
linePoint,
|
||||
GraphicApp,
|
||||
} from 'src/jl-graphic';
|
||||
import {
|
||||
IPathLineData,
|
||||
PathLine,
|
||||
PathLineTemplate,
|
||||
pathLineConsts,
|
||||
} from './PathLine';
|
||||
import {
|
||||
PolylineEditPlugin,
|
||||
addWayPoint,
|
||||
addWaypointConfig,
|
||||
clearWayPoint,
|
||||
clearWaypointsConfig,
|
||||
getWaypointRangeIndex,
|
||||
} from 'src/jl-graphic/plugins/GraphicEditPlugin';
|
||||
import {
|
||||
FederatedPointerEvent,
|
||||
Point,
|
||||
Graphics,
|
||||
LINE_JOIN,
|
||||
IHitArea,
|
||||
DisplayObject,
|
||||
FederatedMouseEvent,
|
||||
} from 'pixi.js';
|
||||
|
||||
export interface IPathLineDrawOptions {
|
||||
newData: () => IPathLineData;
|
||||
}
|
||||
|
||||
export class PathLineDraw extends GraphicDrawAssistant<
|
||||
PathLineTemplate,
|
||||
IPathLineData
|
||||
> {
|
||||
points: Point[] = [];
|
||||
graphic: Graphics = new Graphics();
|
||||
|
||||
constructor(app: JlDrawApp, createData: () => IPathLineData) {
|
||||
super(
|
||||
app,
|
||||
new PathLineTemplate(),
|
||||
createData,
|
||||
'sym_o_horizontal_rule',
|
||||
'不展示'
|
||||
);
|
||||
this.container.addChild(this.graphic);
|
||||
PathLinePointsEditPlugin.init(app);
|
||||
}
|
||||
|
||||
bind(): void {
|
||||
super.bind();
|
||||
}
|
||||
unbind(): void {
|
||||
super.unbind();
|
||||
}
|
||||
clearCache(): void {
|
||||
this.points = [];
|
||||
this.graphic.clear();
|
||||
}
|
||||
// onRightClick(): void {
|
||||
// this.createAndStore(true);
|
||||
// }
|
||||
|
||||
// onLeftDown(e: FederatedPointerEvent): void {
|
||||
// const { x, y } = this.toCanvasCoordinates(e.global);
|
||||
// const p = new Point(x, y);
|
||||
// this.points.push(p);
|
||||
// }
|
||||
quickCreate(points: Point[]) {
|
||||
this.points = [...points];
|
||||
return this.createAndStore(true);
|
||||
}
|
||||
|
||||
redraw(p: Point): void {
|
||||
if (this.points.length < 1) return;
|
||||
this.graphic.clear();
|
||||
const template = this.graphicTemplate;
|
||||
this.graphic.lineStyle({
|
||||
width: template.pathLineWidth,
|
||||
color: template.pathLineColor,
|
||||
join: LINE_JOIN.ROUND,
|
||||
});
|
||||
const ps = [...this.points];
|
||||
ps.push(p);
|
||||
// 直线
|
||||
this.graphic.moveTo(ps[0].x, ps[0].y);
|
||||
for (let i = 1; i < ps.length; i++) {
|
||||
const p = ps[i];
|
||||
this.graphic.lineTo(p.x, p.y);
|
||||
}
|
||||
}
|
||||
prepareData(data: IPathLineData): boolean {
|
||||
data.points = this.points;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class PathLineGraphicHitArea implements IHitArea {
|
||||
pathLine: PathLine;
|
||||
constructor(pathLine: PathLine) {
|
||||
this.pathLine = pathLine;
|
||||
}
|
||||
contains(x: number, y: number): boolean {
|
||||
const p = new Point(x, y);
|
||||
for (let i = 1; i < this.pathLine.datas.points.length; i++) {
|
||||
const p1 = this.pathLine.datas.points[i - 1];
|
||||
const p2 = this.pathLine.datas.points[i];
|
||||
if (linePoint(p1, p2, p, pathLineConsts.pathLineWidth)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class PathLinePointsEditPlugin extends GraphicInteractionPlugin<PathLine> {
|
||||
static Name = 'LinkPointsDrag';
|
||||
constructor(app: GraphicApp) {
|
||||
super(PathLinePointsEditPlugin.Name, app);
|
||||
}
|
||||
static init(app: GraphicApp): PathLinePointsEditPlugin {
|
||||
return new PathLinePointsEditPlugin(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): PathLine[] | undefined {
|
||||
return grahpics.filter((g) => g.type == PathLine.Type) as PathLine[];
|
||||
}
|
||||
bind(g: PathLine): void {
|
||||
g.pathLine.eventMode = 'static';
|
||||
g.pathLine.cursor = 'pointer';
|
||||
g.pathLine.hitArea = new PathLineGraphicHitArea(g);
|
||||
g.on('_rightclick', this.onContextMenu, this);
|
||||
g.on('selected', this.onSelected, this);
|
||||
g.on('unselected', this.onUnselected, this);
|
||||
}
|
||||
unbind(g: PathLine): void {
|
||||
g.off('_rightclick', this.onContextMenu, this);
|
||||
g.off('selected', this.onSelected, this);
|
||||
g.off('unselected', this.onUnselected, this);
|
||||
}
|
||||
|
||||
onContextMenu(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const runLine = target.getGraphic() as PathLine;
|
||||
this.app.updateSelected(runLine);
|
||||
|
||||
addWaypointConfig.handler = () => {
|
||||
const linePoints = runLine.linePoints;
|
||||
const p = runLine.screenToLocalPoint(e.global);
|
||||
const { start, end } = getWaypointRangeIndex(linePoints, false, p);
|
||||
addWayPoint(runLine, false, start, end, p);
|
||||
};
|
||||
clearWaypointsConfig.handler = () => {
|
||||
clearWayPoint(runLine, false);
|
||||
};
|
||||
}
|
||||
|
||||
onSelected(g: DisplayObject): void {
|
||||
const runLine = g as PathLine;
|
||||
let lep;
|
||||
lep = runLine.getAssistantAppend<PolylineEditPlugin>(
|
||||
PolylineEditPlugin.Name
|
||||
);
|
||||
if (!lep) {
|
||||
lep = new PolylineEditPlugin(runLine);
|
||||
runLine.addAssistantAppend(lep);
|
||||
}
|
||||
lep.showAll();
|
||||
}
|
||||
onUnselected(g: DisplayObject): void {
|
||||
const runLine = g as PathLine;
|
||||
const lep = runLine.getAssistantAppend<PolylineEditPlugin>(
|
||||
PolylineEditPlugin.Name
|
||||
);
|
||||
if (lep) {
|
||||
lep.hideAll();
|
||||
}
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ export class PlatformDraw extends GraphicDrawAssistant<
|
||||
app,
|
||||
new PlatformTemplate(),
|
||||
createData,
|
||||
'svguse:/drawIcon.svg#icon-platform',
|
||||
'svguse:../../drawIcon.svg#icon-platform',
|
||||
'站台Platform'
|
||||
);
|
||||
this.container.addChild(this.platformGraphic);
|
||||
|
70
src/graphics/polygon/Polygon.ts
Normal file
70
src/graphics/polygon/Polygon.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { Color, Graphics, IPointData } from 'pixi.js';
|
||||
import { GraphicData, JlGraphic, JlGraphicTemplate } from 'src/jl-graphic';
|
||||
|
||||
export interface IPolygonData extends GraphicData {
|
||||
get code(): string; // 编号
|
||||
set code(v: string);
|
||||
get lineWidth(): number; // 线宽
|
||||
set lineWidth(v: number);
|
||||
get lineColor(): string; // 线色
|
||||
set lineColor(v: string);
|
||||
get points(): IPointData[]; // 多边形坐标点
|
||||
set points(points: IPointData[]);
|
||||
clone(): IPolygonData;
|
||||
copyFrom(data: IPolygonData): void;
|
||||
eq(other: IPolygonData): boolean;
|
||||
}
|
||||
|
||||
const polygonConsts = {
|
||||
lineWidth: 2,
|
||||
lineColor: '0xff0000',
|
||||
};
|
||||
|
||||
export class Polygon extends JlGraphic {
|
||||
static Type = 'Polygon';
|
||||
polygonGraphic: Graphics;
|
||||
constructor() {
|
||||
super(Polygon.Type);
|
||||
this.polygonGraphic = new Graphics();
|
||||
this.addChild(this.polygonGraphic);
|
||||
}
|
||||
|
||||
get datas(): IPolygonData {
|
||||
return this.getDatas<IPolygonData>();
|
||||
}
|
||||
doRepaint(): void {
|
||||
const polygonGraphic = this.polygonGraphic;
|
||||
polygonGraphic.clear();
|
||||
polygonGraphic.lineStyle(
|
||||
this.datas.lineWidth,
|
||||
new Color(this.datas.lineColor)
|
||||
);
|
||||
polygonGraphic.drawPolygon(this.datas.points);
|
||||
}
|
||||
get linePoints(): IPointData[] {
|
||||
return this.datas.points;
|
||||
}
|
||||
set linePoints(points: IPointData[]) {
|
||||
const old = this.datas.clone();
|
||||
old.points = points;
|
||||
this.updateData(old);
|
||||
}
|
||||
addOnePoints(): IPointData[] {
|
||||
const ps = [...this.datas.points];
|
||||
ps.push(this.datas.points[0]);
|
||||
return ps;
|
||||
}
|
||||
}
|
||||
|
||||
export class PolygonTemplate extends JlGraphicTemplate<Polygon> {
|
||||
lineWidth: number;
|
||||
lineColor: string;
|
||||
constructor() {
|
||||
super(Polygon.Type);
|
||||
this.lineWidth = polygonConsts.lineWidth;
|
||||
this.lineColor = polygonConsts.lineColor;
|
||||
}
|
||||
new(): Polygon {
|
||||
return new Polygon();
|
||||
}
|
||||
}
|
270
src/graphics/polygon/PolygonDrawAssistant.ts
Normal file
270
src/graphics/polygon/PolygonDrawAssistant.ts
Normal file
@ -0,0 +1,270 @@
|
||||
import {
|
||||
FederatedPointerEvent,
|
||||
Graphics,
|
||||
Point,
|
||||
IHitArea,
|
||||
DisplayObject,
|
||||
FederatedMouseEvent,
|
||||
} from 'pixi.js';
|
||||
import {
|
||||
DraggablePoint,
|
||||
GraphicApp,
|
||||
GraphicDrawAssistant,
|
||||
GraphicInteractionPlugin,
|
||||
GraphicTransformEvent,
|
||||
JlDrawApp,
|
||||
JlGraphic,
|
||||
calculateLineSegmentingPoint,
|
||||
linePoint,
|
||||
} from 'src/jl-graphic';
|
||||
|
||||
import AbsorbablePoint, {
|
||||
AbsorbablePosition,
|
||||
} from 'src/jl-graphic/graphic/AbsorbablePosition';
|
||||
import {
|
||||
ILineGraphic,
|
||||
PolylineEditPlugin,
|
||||
addWaySegmentingConfig,
|
||||
clearWayPoint,
|
||||
clearWaypointsConfig,
|
||||
getWayLineIndex,
|
||||
} from 'src/jl-graphic/plugins/GraphicEditPlugin';
|
||||
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
|
||||
|
||||
import { IPolygonData, Polygon, PolygonTemplate } from './Polygon';
|
||||
import { Link } from '../link/Link';
|
||||
|
||||
export interface IPolygonDrawOptions {
|
||||
newData: () => IPolygonData;
|
||||
}
|
||||
|
||||
export class PolygonDraw extends GraphicDrawAssistant<
|
||||
PolygonTemplate,
|
||||
IPolygonData
|
||||
> {
|
||||
points: Point[] = [];
|
||||
polygonGraphic: Graphics = new Graphics();
|
||||
|
||||
constructor(app: JlDrawApp, createData: () => IPolygonData) {
|
||||
super(
|
||||
app,
|
||||
new PolygonTemplate(),
|
||||
createData,
|
||||
'sym_o_square',
|
||||
'多边形Polygon'
|
||||
);
|
||||
this.container.addChild(this.polygonGraphic);
|
||||
PolygonPointsEditPlugin.init(app);
|
||||
}
|
||||
|
||||
bind(): void {
|
||||
super.bind();
|
||||
}
|
||||
unbind(): void {
|
||||
super.unbind();
|
||||
}
|
||||
|
||||
clearCache(): void {
|
||||
this.points = [];
|
||||
this.polygonGraphic.clear();
|
||||
}
|
||||
onLeftDown(e: FederatedPointerEvent): void {
|
||||
const { x, y } = this.toCanvasCoordinates(e.global);
|
||||
const p = new Point(x, y);
|
||||
this.points.push(p);
|
||||
}
|
||||
onRightClick(): void {
|
||||
this.createAndStore(true);
|
||||
}
|
||||
redraw(p: Point): void {
|
||||
if (this.points.length < 1) return;
|
||||
const polygonGraphic = this.polygonGraphic;
|
||||
const template = this.graphicTemplate;
|
||||
const ps = [...this.points];
|
||||
ps.push(p);
|
||||
polygonGraphic.clear();
|
||||
polygonGraphic.lineStyle(template.lineWidth, template.lineColor);
|
||||
polygonGraphic.drawPolygon(ps);
|
||||
}
|
||||
|
||||
prepareData(data: IPolygonData): boolean {
|
||||
if (this.points.length < 2) {
|
||||
console.log('Polygon绘制因点不够取消绘制');
|
||||
return false;
|
||||
}
|
||||
const template = this.graphicTemplate;
|
||||
data.lineWidth = template.lineWidth;
|
||||
data.lineColor = template.lineColor;
|
||||
data.points = this.points;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//碰撞检测
|
||||
export class PolygonGraphicHitArea implements IHitArea {
|
||||
polygon: Polygon;
|
||||
constructor(polygon: Polygon) {
|
||||
this.polygon = polygon;
|
||||
}
|
||||
contains(x: number, y: number): boolean {
|
||||
let contains = false;
|
||||
const p = new Point(x, y);
|
||||
const polygonData = this.polygon.datas;
|
||||
//contains = pointPolygon(p, polygonData.points, polygonData.lineWidth);是否包含多边形内部
|
||||
const ps = this.polygon.addOnePoints();
|
||||
const tolerance = polygonData.lineWidth;
|
||||
for (let i = 0; i < ps.length - 1; i++) {
|
||||
const p1 = ps[i];
|
||||
const p2 = ps[i + 1];
|
||||
contains = contains || linePoint(p1, p2, p, tolerance);
|
||||
if (contains) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return contains;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建吸附位置
|
||||
* @param polygon
|
||||
* @returns
|
||||
*/
|
||||
function buildAbsorbablePositions(polygon: Polygon): AbsorbablePosition[] {
|
||||
const aps: AbsorbablePosition[] = [];
|
||||
const polygons = polygon.queryStore.queryByType<Polygon>(Polygon.Type);
|
||||
const links = polygon.queryStore.queryByType<Link>(Link.Type);
|
||||
|
||||
links.forEach((other) => {
|
||||
const apa = new AbsorbablePoint(
|
||||
other.localToCanvasPoint(other.getStartPoint())
|
||||
);
|
||||
const apb = new AbsorbablePoint(
|
||||
other.localToCanvasPoint(other.getEndPoint())
|
||||
);
|
||||
aps.push(apa, apb);
|
||||
});
|
||||
|
||||
polygons.forEach((other) => {
|
||||
if (other.id == polygon.id) {
|
||||
return;
|
||||
}
|
||||
other.linePoints.forEach((point) => {
|
||||
const absorbablePoint = new AbsorbablePoint(
|
||||
other.localToCanvasPoint(point)
|
||||
);
|
||||
aps.push(absorbablePoint);
|
||||
});
|
||||
});
|
||||
|
||||
return aps;
|
||||
}
|
||||
|
||||
/**
|
||||
* 端点拖拽添加吸附位置
|
||||
* @param g
|
||||
* @param dp
|
||||
* @param index
|
||||
*/
|
||||
function onEditPointCreate(g: ILineGraphic, dp: DraggablePoint): void {
|
||||
const polygon = g as Polygon;
|
||||
// 端点
|
||||
dp.on('transformstart', (e: GraphicTransformEvent) => {
|
||||
if (e.isShift()) {
|
||||
polygon.getGraphicApp().setOptions({
|
||||
absorbablePositions: buildAbsorbablePositions(polygon),
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const PolygonEditMenu: ContextMenu = ContextMenu.init({
|
||||
name: '矩形编辑菜单',
|
||||
groups: [
|
||||
{
|
||||
items: [addWaySegmentingConfig, clearWaypointsConfig],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
/**
|
||||
* polygon路径编辑
|
||||
*/
|
||||
export class PolygonPointsEditPlugin extends GraphicInteractionPlugin<Polygon> {
|
||||
static Name = 'PolygonPointsDrag';
|
||||
constructor(app: GraphicApp) {
|
||||
super(PolygonPointsEditPlugin.Name, app);
|
||||
app.registerMenu(PolygonEditMenu);
|
||||
}
|
||||
static init(app: GraphicApp): PolygonPointsEditPlugin {
|
||||
return new PolygonPointsEditPlugin(app);
|
||||
}
|
||||
filter(...grahpics: JlGraphic[]): Polygon[] | undefined {
|
||||
return grahpics.filter((g) => g.type == Polygon.Type) as Polygon[];
|
||||
}
|
||||
bind(g: Polygon): void {
|
||||
g.polygonGraphic.eventMode = 'static';
|
||||
g.polygonGraphic.cursor = 'pointer';
|
||||
g.polygonGraphic.hitArea = new PolygonGraphicHitArea(g);
|
||||
g.on('_rightclick', this.onContextMenu, this);
|
||||
g.on('selected', this.onSelected, this);
|
||||
g.on('unselected', this.onUnselected, this);
|
||||
}
|
||||
unbind(g: Polygon): void {
|
||||
g.off('_rightclick', this.onContextMenu, this);
|
||||
g.off('selected', this.onSelected, this);
|
||||
g.off('unselected', this.onUnselected, this);
|
||||
}
|
||||
|
||||
onContextMenu(e: FederatedMouseEvent) {
|
||||
const target = e.target as DisplayObject;
|
||||
const polygon = target.getGraphic() as Polygon;
|
||||
this.app.updateSelected(polygon);
|
||||
addWaySegmentingConfig.handler = () => {
|
||||
const linePoints = polygon.addOnePoints();
|
||||
const p = polygon.screenToLocalPoint(e.global);
|
||||
const { start, end } = getWayLineIndex(linePoints, p);
|
||||
this.addPolygonSegmentingPoint(polygon, start, end);
|
||||
};
|
||||
clearWaypointsConfig.handler = () => {
|
||||
clearWayPoint(polygon, false);
|
||||
};
|
||||
PolygonEditMenu.open(e.global);
|
||||
}
|
||||
addPolygonSegmentingPoint(
|
||||
graphic: Polygon,
|
||||
start: number,
|
||||
end: number,
|
||||
knife = 2
|
||||
) {
|
||||
const linePoints = graphic.addOnePoints();
|
||||
const points = linePoints.slice(0, start + 1);
|
||||
points.push(
|
||||
...calculateLineSegmentingPoint(linePoints[start], linePoints[end], knife)
|
||||
);
|
||||
points.push(...linePoints.slice(end));
|
||||
points.pop();
|
||||
graphic.linePoints = points;
|
||||
}
|
||||
|
||||
onSelected(g: DisplayObject): void {
|
||||
const polygon = g as Polygon;
|
||||
let lep = polygon.getAssistantAppend<PolylineEditPlugin>(
|
||||
PolylineEditPlugin.Name
|
||||
);
|
||||
if (!lep) {
|
||||
lep = new PolylineEditPlugin(polygon, { onEditPointCreate });
|
||||
polygon.addAssistantAppend(lep);
|
||||
}
|
||||
lep.showAll();
|
||||
}
|
||||
onUnselected(g: DisplayObject): void {
|
||||
const polygon = g as Polygon;
|
||||
const lep = polygon.getAssistantAppend<PolylineEditPlugin>(
|
||||
PolylineEditPlugin.Name
|
||||
);
|
||||
if (lep) {
|
||||
lep.hideAll();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,14 @@
|
||||
import { Graphics, IPointData, LINE_JOIN } from 'pixi.js';
|
||||
import { GraphicData, JlGraphic, JlGraphicTemplate } from 'src/jl-graphic';
|
||||
import { Graphics, IPointData, LINE_JOIN, Point } from 'pixi.js';
|
||||
import {
|
||||
GraphicData,
|
||||
JlDrawApp,
|
||||
JlGraphic,
|
||||
JlGraphicTemplate,
|
||||
} from 'src/jl-graphic';
|
||||
import { RunLineName } from './RunLineName';
|
||||
import { PathLine } from '../pathLine/PathLine';
|
||||
import { PathLineDraw } from '../pathLine/PathLineDrawAssistant';
|
||||
import { getDrawApp } from 'src/drawApp';
|
||||
|
||||
export interface IRunLineData extends GraphicData {
|
||||
get code(): string;
|
||||
@ -11,6 +19,11 @@ export interface IRunLineData extends GraphicData {
|
||||
set nameColor(v: string);
|
||||
get nameBgColor(): string;
|
||||
set nameBgColor(v: string);
|
||||
get upPathLineId(): string;
|
||||
set upPathLineId(v: string);
|
||||
get downPathLineId(): string;
|
||||
set downPathLineId(v: string);
|
||||
|
||||
clone(): IRunLineData;
|
||||
copyFrom(data: IRunLineData): void;
|
||||
eq(other: IRunLineData): boolean;
|
||||
@ -81,12 +94,53 @@ export class RunLine extends JlGraphic {
|
||||
old.points = points;
|
||||
this.updateData(old);
|
||||
}
|
||||
|
||||
generatePathLine(pointsUp: Point[], pointsDown: Point[]) {
|
||||
const app = this.getGraphicApp() as JlDrawApp;
|
||||
const pathLineDrawAssistant = app.getDrawAssistant(
|
||||
PathLine.Type
|
||||
) as PathLineDraw;
|
||||
if (this.datas.upPathLineId) {
|
||||
const oldUp = app.queryStore.queryById(this.datas.upPathLineId);
|
||||
if (oldUp) {
|
||||
app.deleteGraphics(oldUp);
|
||||
}
|
||||
}
|
||||
if (this.datas.downPathLineId) {
|
||||
const oldDown = app.queryStore.queryById(this.datas.downPathLineId);
|
||||
if (oldDown) {
|
||||
app.deleteGraphics(oldDown);
|
||||
}
|
||||
}
|
||||
const pathLineUp = pathLineDrawAssistant.quickCreate(pointsUp);
|
||||
const pathLineDown = pathLineDrawAssistant.quickCreate(pointsDown);
|
||||
this.datas.upPathLineId = pathLineUp?.id || '';
|
||||
this.datas.downPathLineId = pathLineDown?.id || '';
|
||||
}
|
||||
|
||||
getStartPoint(): IPointData {
|
||||
return this.datas.points[0];
|
||||
}
|
||||
getEndPoint(): IPointData {
|
||||
return this.datas.points[this.datas.points.length - 1];
|
||||
}
|
||||
onDelete(): void {
|
||||
super.onDelete();
|
||||
const app = getDrawApp();
|
||||
if (!app) return;
|
||||
if (this.datas.upPathLineId) {
|
||||
const oldUp = app.queryStore.queryById(this.datas.upPathLineId);
|
||||
if (oldUp) {
|
||||
app.deleteGraphics(oldUp);
|
||||
}
|
||||
}
|
||||
if (this.datas.downPathLineId) {
|
||||
const oldDown = app.queryStore.queryById(this.datas.downPathLineId);
|
||||
if (oldDown) {
|
||||
app.deleteGraphics(oldDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class RunLineTemplate extends JlGraphicTemplate<RunLine> {
|
||||
|
@ -48,7 +48,7 @@ export class RunLineDraw extends GraphicDrawAssistant<
|
||||
new RunLineTemplate(),
|
||||
createData,
|
||||
'sym_o_horizontal_rule',
|
||||
'运行线RunLIne'
|
||||
'运行线RunLine'
|
||||
);
|
||||
this.container.addChild(this.graphic);
|
||||
RunLinePointsEditPlugin.init(app);
|
||||
|
@ -23,7 +23,7 @@ export class SignalDraw extends GraphicDrawAssistant<
|
||||
app,
|
||||
new SignalTemplate(),
|
||||
createData,
|
||||
'svguse:/drawIcon.svg#icon-signal',
|
||||
'svguse: ../../drawIcon.svg#icon-signal',
|
||||
'信号机Signal'
|
||||
);
|
||||
|
||||
@ -52,7 +52,7 @@ export class SignalDraw extends GraphicDrawAssistant<
|
||||
onRightClick(): void {
|
||||
this.createAndStore(true);
|
||||
}
|
||||
onLeftDown(e: FederatedPointerEvent): void {
|
||||
onLeftUp(e: FederatedPointerEvent): void {
|
||||
this.container.position.copyFrom(this.toCanvasCoordinates(e.global));
|
||||
this.createAndStore(true);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export class StationDraw extends GraphicDrawAssistant<
|
||||
app,
|
||||
new StationTemplate(),
|
||||
createData,
|
||||
'svguse:/drawIcon.svg#icon-station',
|
||||
'svguse:../../drawIcon.svg#icon-station',
|
||||
'车站Station'
|
||||
);
|
||||
this.codeGraph = this.graphicTemplate.new();
|
||||
|
@ -27,7 +27,7 @@ export class StationLineDraw extends GraphicDrawAssistant<
|
||||
app,
|
||||
new StationLineTemplate(),
|
||||
createData,
|
||||
'svguse:/drawIcon.svg#icon-station',
|
||||
'svguse:../../drawIcon.svg#icon-station',
|
||||
'车站StationLine'
|
||||
);
|
||||
this.codeGraph = this.graphicTemplate.new();
|
||||
|
@ -169,7 +169,7 @@ import {
|
||||
} from 'src/drawApp';
|
||||
import { JlDrawApp } from 'src/jl-graphic';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { errorNotify, successNotify } from 'src/utils/CommonNotify';
|
||||
import { saveAsDraft } from 'src/api/DraftApi';
|
||||
@ -180,6 +180,15 @@ const router = useRouter();
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
|
||||
watch(
|
||||
() => drawStore.drawMode,
|
||||
(drawMode) => {
|
||||
if (!drawMode) {
|
||||
selectUtil.value = '';
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const leftDrawerOpen = ref(false);
|
||||
const rightDrawerOpen = ref(false);
|
||||
function toggleRightDrawer() {
|
||||
@ -229,6 +238,7 @@ onMounted(() => {
|
||||
.drawAssistants;
|
||||
drawAssistants.forEach(
|
||||
(da: { name: string; icon: string; description: string }) => {
|
||||
if (da.description === '不展示') return;
|
||||
utilsOption.push(
|
||||
new ControlItem(
|
||||
da.name,
|
||||
|
Loading…
Reference in New Issue
Block a user