测试
This commit is contained in:
parent
589b8d6952
commit
b0dc4c7e1a
55
components/packages/Turnout/common/TurnoutDrawAssistant.d.ts
vendored
Normal file
55
components/packages/Turnout/common/TurnoutDrawAssistant.d.ts
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { AbsorbablePosition, DraggablePoint, IGraphicApp, GraphicDrawAssistant, GraphicInteractionPlugin, GraphicTransformEvent, IDrawApp, JlGraphic, VectorText, GraphicEditPlugin, GraphicState } from 'jl-graphic';
|
||||||
|
import { JlTurnout, TurnoutSection } from './JlTurnout';
|
||||||
|
import { DisplayObject, FederatedMouseEvent, IHitArea, Point } from 'pixi.js';
|
||||||
|
import { ITurnoutData } from './TurnoutConfig';
|
||||||
|
import { TurnoutTemplate } from './TurnoutTemplate';
|
||||||
|
import { JlSection } from 'src/packages/Section/common/JlSection';
|
||||||
|
export declare class TurnoutDraw<S extends GraphicState> extends GraphicDrawAssistant<TurnoutTemplate<S>, ITurnoutData> {
|
||||||
|
turnout: JlTurnout;
|
||||||
|
constructor(app: IDrawApp, template: TurnoutTemplate<S>);
|
||||||
|
bind(): void;
|
||||||
|
onLeftUp(e: FederatedMouseEvent): void;
|
||||||
|
prepareData(data: ITurnoutData): boolean;
|
||||||
|
redraw(cp: Point): void;
|
||||||
|
}
|
||||||
|
export declare class ForkHitArea implements IHitArea {
|
||||||
|
turnout: JlTurnout;
|
||||||
|
constructor(turnout: JlTurnout);
|
||||||
|
contains(x: number, y: number): boolean;
|
||||||
|
}
|
||||||
|
export declare class TurnoutSectionHitArea implements IHitArea {
|
||||||
|
section: TurnoutSection;
|
||||||
|
constructor(section: TurnoutSection);
|
||||||
|
contains(x: number, y: number): boolean;
|
||||||
|
}
|
||||||
|
type dragType = JlTurnout | JlSection;
|
||||||
|
export declare function buildDragMoveAbsorbablePositions(target: dragType): AbsorbablePosition[];
|
||||||
|
export declare class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<JlTurnout> {
|
||||||
|
static Name: string;
|
||||||
|
static init(app: IDrawApp): TurnoutPointsInteractionPlugin;
|
||||||
|
constructor(app: IGraphicApp);
|
||||||
|
onSectionContextMenu(e: FederatedMouseEvent, section: TurnoutSection): void;
|
||||||
|
bind(g: JlTurnout): void;
|
||||||
|
unbind(g: JlTurnout): void;
|
||||||
|
onSelected(g: DisplayObject): void;
|
||||||
|
onUnSelected(g: DisplayObject): void;
|
||||||
|
filter(...grahpics: JlGraphic[]): JlTurnout[] | undefined;
|
||||||
|
onDragMove(e: GraphicTransformEvent): void;
|
||||||
|
}
|
||||||
|
type onTurnoutEditPointCreate = (turnout: JlTurnout, dp: DraggablePoint) => void;
|
||||||
|
export interface ITurnoutEditOptions {
|
||||||
|
onEditPointCreate?: onTurnoutEditPointCreate;
|
||||||
|
}
|
||||||
|
export declare class TurnoutEditPlugin extends GraphicEditPlugin<JlTurnout> {
|
||||||
|
static Name: string;
|
||||||
|
options: ITurnoutEditOptions;
|
||||||
|
editPoints: DraggablePoint[][];
|
||||||
|
labels: VectorText[];
|
||||||
|
constructor(graphic: JlTurnout, options?: ITurnoutEditOptions);
|
||||||
|
reset(): void;
|
||||||
|
hideAll(): void;
|
||||||
|
initEditPoints(): void;
|
||||||
|
destoryEditPoints(): void;
|
||||||
|
updateEditedPointsPosition(): void;
|
||||||
|
}
|
||||||
|
export {};
|
389
components/packages/Turnout/common/TurnoutDrawAssistant.js
Normal file
389
components/packages/Turnout/common/TurnoutDrawAssistant.js
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
import { ContextMenu, GraphicDrawAssistant, linePoint, polylinePoint, GraphicInteractionPlugin, getWaypointRangeIndex, GraphicEditPlugin, DraggablePoint, VectorText, AppConsts, AbsorbablePoint, distance, AbsorbableLine } from 'jl-graphic';
|
||||||
|
import { getForkPoint, JlTurnout } from './JlTurnout.js';
|
||||||
|
import { Point } from 'pixi.js';
|
||||||
|
import { DevicePort } from '../../../common/common.js';
|
||||||
|
import { JlSection } from '../../Section/common/JlSection.js';
|
||||||
|
|
||||||
|
const commonTurnoutConsts = {
|
||||||
|
lineWidth: 5,
|
||||||
|
forkLenth: 20,
|
||||||
|
};
|
||||||
|
class TurnoutDraw extends GraphicDrawAssistant {
|
||||||
|
turnout;
|
||||||
|
constructor(app, template) {
|
||||||
|
super(app, template, 'sym_o_ramp_left', '道岔Turnout');
|
||||||
|
this.turnout = this.graphicTemplate.new();
|
||||||
|
this.container.addChild(this.turnout);
|
||||||
|
TurnoutPointsInteractionPlugin.init(app);
|
||||||
|
}
|
||||||
|
bind() {
|
||||||
|
super.bind();
|
||||||
|
this.turnout.loadData(this.graphicTemplate.datas);
|
||||||
|
this.turnout.doRepaint();
|
||||||
|
}
|
||||||
|
onLeftUp(e) {
|
||||||
|
this.turnout.position.copyFrom(this.toCanvasCoordinates(e.global));
|
||||||
|
this.createAndStore(true);
|
||||||
|
}
|
||||||
|
prepareData(data) {
|
||||||
|
data.transform = this.turnout.saveTransform();
|
||||||
|
data.code = 'A000000';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
redraw(cp) {
|
||||||
|
this.turnout.position.copyFrom(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ForkHitArea {
|
||||||
|
turnout;
|
||||||
|
constructor(turnout) {
|
||||||
|
this.turnout = turnout;
|
||||||
|
}
|
||||||
|
contains(x, y) {
|
||||||
|
const intersectPointB = getForkPoint(commonTurnoutConsts.forkLenth, this.turnout.datas.pointB[0]);
|
||||||
|
const intersectPointC = getForkPoint(commonTurnoutConsts.forkLenth, this.turnout.datas.pointC[0]);
|
||||||
|
return (linePoint(intersectPointB, { x: 0, y: 0 }, { x, y }, commonTurnoutConsts.lineWidth) ||
|
||||||
|
linePoint(intersectPointC, { x: 0, y: 0 }, { x, y }, commonTurnoutConsts.lineWidth));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class TurnoutSectionHitArea {
|
||||||
|
section;
|
||||||
|
constructor(section) {
|
||||||
|
this.section = section;
|
||||||
|
}
|
||||||
|
contains(x, y) {
|
||||||
|
let points;
|
||||||
|
let start;
|
||||||
|
switch (this.section.port) {
|
||||||
|
case DevicePort.A:
|
||||||
|
points = this.section.turnout.datas.pointA;
|
||||||
|
start = { x: 0, y: 0 };
|
||||||
|
break;
|
||||||
|
case DevicePort.B:
|
||||||
|
points = this.section.turnout.datas.pointB;
|
||||||
|
start = getForkPoint(commonTurnoutConsts.forkLenth, points[0]);
|
||||||
|
break;
|
||||||
|
case DevicePort.C:
|
||||||
|
points = this.section.turnout.datas.pointC;
|
||||||
|
start = getForkPoint(commonTurnoutConsts.forkLenth, points[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return polylinePoint([start, ...points], { x, y }, commonTurnoutConsts.lineWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function buildAbsorbablePositions(turnout) {
|
||||||
|
const aps = [];
|
||||||
|
const sections = turnout.queryStore.queryByType(JlSection.Type);
|
||||||
|
sections.forEach((section) => {
|
||||||
|
const ps = new AbsorbablePoint(section.localToCanvasPoint(section.getStartPoint()));
|
||||||
|
const pe = new AbsorbablePoint(section.localToCanvasPoint(section.getEndPoint()));
|
||||||
|
aps.push(ps, pe); //区段端点
|
||||||
|
});
|
||||||
|
const turnouts = turnout.queryStore.queryByType(JlTurnout.Type);
|
||||||
|
turnouts.forEach((otherTurnout) => {
|
||||||
|
const { pointA: [A], pointB: [B], pointC: [C], } = otherTurnout.datas;
|
||||||
|
[A, B, C].forEach((p) => {
|
||||||
|
aps.push(new AbsorbablePoint(otherTurnout.localToCanvasPoint(p)), //道岔端点
|
||||||
|
new AbsorbableLine(otherTurnout.localToCanvasPoint({ x: -5 * p.x, y: -5 * p.y }), otherTurnout.localToCanvasPoint({ x: 5 * p.x, y: 5 * p.y })));
|
||||||
|
});
|
||||||
|
aps.push(new AbsorbableLine(otherTurnout.localToCanvasPoint({ x: 0, y: -500 }), otherTurnout.localToCanvasPoint({ x: 0, y: 500 })), //岔心垂直线
|
||||||
|
new AbsorbableLine(otherTurnout.localToCanvasPoint({ x: -500, y: 0 }), otherTurnout.localToCanvasPoint({ x: 500, y: 0 })), //岔心水平线
|
||||||
|
new AbsorbableLine(otherTurnout.localToCanvasPoint({ x: -500, y: 500 }), otherTurnout.localToCanvasPoint({ x: 500, y: -500 })), //岔心/
|
||||||
|
new AbsorbableLine(otherTurnout.localToCanvasPoint({ x: -500, y: -500 }), otherTurnout.localToCanvasPoint({ x: 500, y: 500 })));
|
||||||
|
});
|
||||||
|
return aps;
|
||||||
|
}
|
||||||
|
class DragMoveAbsorbablePoint extends AbsorbablePoint {
|
||||||
|
moveTarget;
|
||||||
|
constructor(point, absorbRange = 15) {
|
||||||
|
super(point, absorbRange);
|
||||||
|
}
|
||||||
|
tryAbsorb(...dragTargets) {
|
||||||
|
const dragTarget = dragTargets[0];
|
||||||
|
if (dragTarget instanceof JlTurnout) {
|
||||||
|
if (this.moveTarget == undefined) {
|
||||||
|
const { pointA: [A], pointB: [B], pointC: [C], } = dragTarget.datas;
|
||||||
|
this.moveTarget = {
|
||||||
|
position: dragTarget.getGlobalPosition(),
|
||||||
|
portPos: [
|
||||||
|
dragTarget.localToCanvasPoint(A),
|
||||||
|
dragTarget.localToCanvasPoint(B),
|
||||||
|
dragTarget.localToCanvasPoint(C),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const { pointA: [A], pointB: [B], pointC: [C], } = dragTarget.datas;
|
||||||
|
[A, B, C].forEach((p, i) => {
|
||||||
|
const changePos = dragTarget.localToCanvasPoint(p);
|
||||||
|
if (distance(this._point.x, this._point.y, changePos.x, changePos.y) <
|
||||||
|
this.absorbRange &&
|
||||||
|
this.moveTarget) {
|
||||||
|
dragTarget.updatePositionByCanvasPosition(new Point(this.moveTarget.position.x +
|
||||||
|
this._point.x -
|
||||||
|
this.moveTarget.portPos[i].x, this.moveTarget.position.y +
|
||||||
|
this._point.y -
|
||||||
|
this.moveTarget.portPos[i].y));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.moveTarget == undefined) {
|
||||||
|
this.moveTarget = {
|
||||||
|
position: dragTarget.getGlobalPosition(),
|
||||||
|
portPos: [
|
||||||
|
dragTarget.localToCanvasPoint(dragTarget.getStartPoint()),
|
||||||
|
dragTarget.localToCanvasPoint(dragTarget.getEndPoint()),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
dragTarget
|
||||||
|
.localToCanvasPoints(...dragTarget.datas.points)
|
||||||
|
.forEach((p, i) => {
|
||||||
|
if (distance(this._point.x, this._point.y, p.x, p.y) <
|
||||||
|
this.absorbRange &&
|
||||||
|
this.moveTarget) {
|
||||||
|
dragTarget.updatePositionByCanvasPosition(new Point(this.moveTarget.position.x +
|
||||||
|
this._point.x -
|
||||||
|
this.moveTarget.portPos[i].x, this.moveTarget.position.y +
|
||||||
|
this._point.y -
|
||||||
|
this.moveTarget.portPos[i].y));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function buildDragMoveAbsorbablePositions(target) {
|
||||||
|
const aps = [];
|
||||||
|
const sections = target.queryStore.queryByType(JlSection.Type);
|
||||||
|
sections.forEach((section) => {
|
||||||
|
if (section.id !== target.id) {
|
||||||
|
section.localToCanvasPoints(...section.datas.points).forEach((p) => {
|
||||||
|
aps.push(new DragMoveAbsorbablePoint(p)); //区段端点
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const turnouts = target.queryStore.queryByType(JlTurnout.Type);
|
||||||
|
turnouts.forEach((otherTurnout) => {
|
||||||
|
if (otherTurnout.id !== target.id) {
|
||||||
|
const { pointA: [A], pointB: [B], pointC: [C], } = otherTurnout.datas;
|
||||||
|
[A, B, C].forEach((p) => {
|
||||||
|
aps.push(new DragMoveAbsorbablePoint(otherTurnout.localToCanvasPoint(p)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return aps;
|
||||||
|
}
|
||||||
|
function onEditPointCreate(turnout, dp) {
|
||||||
|
dp.on('transformstart', (e) => {
|
||||||
|
if (e.isShift()) {
|
||||||
|
turnout.getGraphicApp().setOptions({
|
||||||
|
absorbablePositions: buildAbsorbablePositions(turnout),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const addPointConfig = { name: '添加路径点' };
|
||||||
|
const clearPointConfig = { name: '清除路径点' };
|
||||||
|
const turnoutSectionEditMenu = ContextMenu.init({
|
||||||
|
name: '道岔区段路径编辑',
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
items: [addPointConfig, clearPointConfig],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin {
|
||||||
|
static Name = 'TurnoutPointsDrag';
|
||||||
|
static init(app) {
|
||||||
|
return new TurnoutPointsInteractionPlugin(app);
|
||||||
|
}
|
||||||
|
constructor(app) {
|
||||||
|
super(TurnoutPointsInteractionPlugin.Name, app);
|
||||||
|
app.registerMenu(turnoutSectionEditMenu);
|
||||||
|
}
|
||||||
|
onSectionContextMenu(e, section) {
|
||||||
|
const p = section.turnout.screenToLocalPoint(e.global);
|
||||||
|
addPointConfig.handler = () => {
|
||||||
|
if (section.port === DevicePort.A) {
|
||||||
|
const { start } = getWaypointRangeIndex([{ x: 0, y: 0 }, ...section.turnout.datas.pointA], false, p, commonTurnoutConsts.lineWidth);
|
||||||
|
const points = section.turnout.datas.pointA;
|
||||||
|
const ps = points.slice(0, start);
|
||||||
|
ps.push(new Point(p.x, p.y));
|
||||||
|
ps.push(...points.slice(start));
|
||||||
|
section.turnout.datas.pointA = ps;
|
||||||
|
}
|
||||||
|
if (section.port === DevicePort.B) {
|
||||||
|
const { start } = getWaypointRangeIndex([{ x: 0, y: 0 }, ...section.turnout.datas.pointB], false, p, commonTurnoutConsts.lineWidth);
|
||||||
|
const points = section.turnout.datas.pointB;
|
||||||
|
const ps = points.slice(0, start);
|
||||||
|
ps.push(new Point(p.x, p.y));
|
||||||
|
ps.push(...points.slice(start));
|
||||||
|
section.turnout.datas.pointB = ps;
|
||||||
|
}
|
||||||
|
if (section.port === DevicePort.C) {
|
||||||
|
const { start } = getWaypointRangeIndex([{ x: 0, y: 0 }, ...section.turnout.datas.pointC], false, p, commonTurnoutConsts.lineWidth);
|
||||||
|
const points = section.turnout.datas.pointC;
|
||||||
|
const ps = points.slice(0, start);
|
||||||
|
ps.push(new Point(p.x, p.y));
|
||||||
|
ps.push(...points.slice(start));
|
||||||
|
section.turnout.datas.pointC = ps;
|
||||||
|
}
|
||||||
|
this.onSelected(section.turnout);
|
||||||
|
};
|
||||||
|
clearPointConfig.handler = () => {
|
||||||
|
if (section.port === DevicePort.A)
|
||||||
|
section.turnout.datas.pointA = [
|
||||||
|
section.turnout.datas.pointA[section.turnout.datas.pointA.length - 1],
|
||||||
|
];
|
||||||
|
if (section.port === DevicePort.B)
|
||||||
|
section.turnout.datas.pointB = [
|
||||||
|
section.turnout.datas.pointB[section.turnout.datas.pointB.length - 1],
|
||||||
|
];
|
||||||
|
if (section.port === DevicePort.C)
|
||||||
|
section.turnout.datas.pointC = [
|
||||||
|
section.turnout.datas.pointC[section.turnout.datas.pointC.length - 1],
|
||||||
|
];
|
||||||
|
const tep = section.turnout.getAssistantAppend(TurnoutEditPlugin.Name);
|
||||||
|
if (tep) {
|
||||||
|
tep.reset();
|
||||||
|
}
|
||||||
|
section.turnout.repaint();
|
||||||
|
};
|
||||||
|
turnoutSectionEditMenu.open(e.global);
|
||||||
|
}
|
||||||
|
bind(g) {
|
||||||
|
g.graphics.fork.eventMode = 'static';
|
||||||
|
g.graphics.fork.cursor = 'pointer';
|
||||||
|
g.graphics.fork.hitArea = new ForkHitArea(g);
|
||||||
|
g.graphics.sections.forEach((sectionGraphic) => {
|
||||||
|
sectionGraphic.eventMode = 'static';
|
||||||
|
sectionGraphic.cursor = 'pointer';
|
||||||
|
sectionGraphic.hitArea = new TurnoutSectionHitArea(sectionGraphic);
|
||||||
|
sectionGraphic.on('rightclick', (e) => this.onSectionContextMenu(e, sectionGraphic), sectionGraphic);
|
||||||
|
});
|
||||||
|
g.graphics.label.eventMode = 'static';
|
||||||
|
g.graphics.label.cursor = 'pointer';
|
||||||
|
g.graphics.label.draggable = true;
|
||||||
|
g.graphics.label.selectable = true;
|
||||||
|
g.graphics.label.name = 'label';
|
||||||
|
g.graphics.label.transformSave = true;
|
||||||
|
g.transformSave = true;
|
||||||
|
g.on('selected', this.onSelected, this);
|
||||||
|
g.on('unselected', this.onUnSelected, this);
|
||||||
|
g.on('transformstart', this.onDragMove, this);
|
||||||
|
}
|
||||||
|
unbind(g) {
|
||||||
|
g.off('selected', this.onSelected, this);
|
||||||
|
g.off('unselected', this.onUnSelected, this);
|
||||||
|
g.graphics.sections.forEach((sectionGraphic) => {
|
||||||
|
sectionGraphic.off('rightclick');
|
||||||
|
});
|
||||||
|
g.off('transformstart', this.onDragMove, this);
|
||||||
|
}
|
||||||
|
onSelected(g) {
|
||||||
|
const turnout = g;
|
||||||
|
let tep = turnout.getAssistantAppend(TurnoutEditPlugin.Name);
|
||||||
|
if (!tep) {
|
||||||
|
tep = new TurnoutEditPlugin(turnout, { onEditPointCreate });
|
||||||
|
turnout.addAssistantAppend(tep);
|
||||||
|
}
|
||||||
|
tep.reset();
|
||||||
|
tep.showAll();
|
||||||
|
}
|
||||||
|
onUnSelected(g) {
|
||||||
|
const turnout = g;
|
||||||
|
const tep = turnout.getAssistantAppend(TurnoutEditPlugin.Name);
|
||||||
|
if (tep) {
|
||||||
|
tep.hideAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filter(...grahpics) {
|
||||||
|
return grahpics.filter((g) => g.type == JlTurnout.Type);
|
||||||
|
}
|
||||||
|
onDragMove(e) {
|
||||||
|
const turnout = e.target;
|
||||||
|
this.app.setOptions({
|
||||||
|
absorbablePositions: buildDragMoveAbsorbablePositions(turnout),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class TurnoutEditPlugin extends GraphicEditPlugin {
|
||||||
|
static Name = 'TurnoutEdit';
|
||||||
|
options;
|
||||||
|
editPoints = [[], [], []];
|
||||||
|
labels = [];
|
||||||
|
constructor(graphic, options) {
|
||||||
|
super(graphic);
|
||||||
|
this.name = TurnoutEditPlugin.Name;
|
||||||
|
this.options = Object.assign({}, options);
|
||||||
|
this.initEditPoints();
|
||||||
|
}
|
||||||
|
reset() {
|
||||||
|
this.destoryEditPoints();
|
||||||
|
this.removeChildren();
|
||||||
|
this.initEditPoints();
|
||||||
|
}
|
||||||
|
hideAll() {
|
||||||
|
super.hideAll();
|
||||||
|
}
|
||||||
|
initEditPoints() {
|
||||||
|
const cpA = this.graphic.localToCanvasPoints(...this.graphic.datas.pointA);
|
||||||
|
const cpB = this.graphic.localToCanvasPoints(...this.graphic.datas.pointB);
|
||||||
|
const cpC = this.graphic.localToCanvasPoints(...this.graphic.datas.pointC);
|
||||||
|
const cpMap = new Map([
|
||||||
|
[cpA, this.graphic.datas.pointA],
|
||||||
|
[cpB, this.graphic.datas.pointB],
|
||||||
|
[cpC, this.graphic.datas.pointC],
|
||||||
|
]);
|
||||||
|
Array.from(cpMap.entries()).forEach(([cpDatas, dataPoints], i) => {
|
||||||
|
cpDatas.forEach((cpData, j) => {
|
||||||
|
const dp = new DraggablePoint(cpData);
|
||||||
|
dp.on('transforming', () => {
|
||||||
|
const localPoint = this.graphic.canvasToLocalPoint(dp.position);
|
||||||
|
dataPoints[j].x = localPoint.x;
|
||||||
|
dataPoints[j].y = localPoint.y;
|
||||||
|
this.graphic.repaint();
|
||||||
|
});
|
||||||
|
if (this.options.onEditPointCreate) {
|
||||||
|
this.options.onEditPointCreate(this.graphic, dp);
|
||||||
|
}
|
||||||
|
this.editPoints[i].push(dp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.editPoints.forEach((cps) => {
|
||||||
|
this.addChild(...cps);
|
||||||
|
});
|
||||||
|
this.labels = ['A', 'B', 'C'].map((str) => {
|
||||||
|
const vc = new VectorText(str, { fill: AppConsts.assistantElementColor });
|
||||||
|
vc.setVectorFontSize(14);
|
||||||
|
vc.anchor.set(0.5);
|
||||||
|
return vc;
|
||||||
|
});
|
||||||
|
this.addChild(...this.labels);
|
||||||
|
}
|
||||||
|
destoryEditPoints() {
|
||||||
|
this.editPoints.forEach((dps) => {
|
||||||
|
dps.forEach((dp) => {
|
||||||
|
dp.off('transforming');
|
||||||
|
dp.destroy();
|
||||||
|
this.removeChild(dp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.editPoints = [[], [], []];
|
||||||
|
}
|
||||||
|
updateEditedPointsPosition() {
|
||||||
|
const cpA = this.graphic.localToCanvasPoints(...this.graphic.datas.pointA);
|
||||||
|
const cpB = this.graphic.localToCanvasPoints(...this.graphic.datas.pointB);
|
||||||
|
const cpC = this.graphic.localToCanvasPoints(...this.graphic.datas.pointC);
|
||||||
|
[cpA, cpB, cpC].forEach((cps, i) => {
|
||||||
|
cps.forEach((cp, j) => {
|
||||||
|
this.editPoints[i][j].position.copyFrom(cp);
|
||||||
|
if (j === cps.length - 1) {
|
||||||
|
this.labels[i].position.copyFrom({ x: cp.x, y: cp.y + 12 });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ForkHitArea, TurnoutDraw, TurnoutEditPlugin, TurnoutPointsInteractionPlugin, TurnoutSectionHitArea, buildDragMoveAbsorbablePositions };
|
9
components/packages/Turnout/common/TurnoutTemplate.d.ts
vendored
Normal file
9
components/packages/Turnout/common/TurnoutTemplate.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { GraphicState, JlGraphicTemplate } from 'jl-graphic';
|
||||||
|
import { JlTurnout } from './JlTurnout';
|
||||||
|
import { ITurnoutData } from './TurnoutConfig';
|
||||||
|
import { StyleType } from 'common/common';
|
||||||
|
export declare class TurnoutTemplate<S extends GraphicState> extends JlGraphicTemplate<JlTurnout> {
|
||||||
|
styleType: StyleType;
|
||||||
|
constructor(dataTemplate: ITurnoutData, stateTemplate: S, styleType: StyleType);
|
||||||
|
new(): JlTurnout;
|
||||||
|
}
|
32
components/packages/Turnout/common/TurnoutTemplate.js
Normal file
32
components/packages/Turnout/common/TurnoutTemplate.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { JlGraphicTemplate } from 'jl-graphic';
|
||||||
|
import { JlTurnout } from './JlTurnout.js';
|
||||||
|
import { StyleType } from '../../../common/common.js';
|
||||||
|
import { GPTurnout } from '../GPTurnout.js';
|
||||||
|
import { THTurnout } from '../THTurnout.js';
|
||||||
|
|
||||||
|
class TurnoutTemplate extends JlGraphicTemplate {
|
||||||
|
styleType;
|
||||||
|
constructor(dataTemplate, stateTemplate, styleType) {
|
||||||
|
super(JlTurnout.Type, {
|
||||||
|
dataTemplate,
|
||||||
|
stateTemplate,
|
||||||
|
});
|
||||||
|
this.styleType = styleType;
|
||||||
|
}
|
||||||
|
new() {
|
||||||
|
let turnout;
|
||||||
|
switch (this.styleType) {
|
||||||
|
case StyleType.GP:
|
||||||
|
turnout = new GPTurnout();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
turnout = new THTurnout();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
turnout.loadData(this.datas);
|
||||||
|
turnout.loadState(this.states);
|
||||||
|
return turnout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { TurnoutTemplate };
|
575
src/packages/Turnout/common/TurnoutDrawAssistant.ts
Normal file
575
src/packages/Turnout/common/TurnoutDrawAssistant.ts
Normal file
@ -0,0 +1,575 @@
|
|||||||
|
import {
|
||||||
|
AbsorbablePosition,
|
||||||
|
DraggablePoint,
|
||||||
|
IGraphicApp,
|
||||||
|
GraphicDrawAssistant,
|
||||||
|
GraphicInteractionPlugin,
|
||||||
|
GraphicTransformEvent,
|
||||||
|
IDrawApp,
|
||||||
|
JlGraphic,
|
||||||
|
VectorText,
|
||||||
|
linePoint,
|
||||||
|
polylinePoint,
|
||||||
|
AppConsts,
|
||||||
|
GraphicEditPlugin,
|
||||||
|
getWaypointRangeIndex,
|
||||||
|
ContextMenu,
|
||||||
|
MenuItemOptions,
|
||||||
|
AbsorbablePoint,
|
||||||
|
AbsorbableLine,
|
||||||
|
distance,
|
||||||
|
GraphicState,
|
||||||
|
} from 'jl-graphic';
|
||||||
|
import { JlTurnout, TurnoutSection, getForkPoint } from './JlTurnout';
|
||||||
|
import {
|
||||||
|
DisplayObject,
|
||||||
|
FederatedMouseEvent,
|
||||||
|
IHitArea,
|
||||||
|
IPointData,
|
||||||
|
Point,
|
||||||
|
} from 'pixi.js';
|
||||||
|
import { ITurnoutData } from './TurnoutConfig';
|
||||||
|
import { TurnoutTemplate } from './TurnoutTemplate';
|
||||||
|
import { DevicePort } from 'common/common';
|
||||||
|
import { JlSection } from 'src/packages/Section/common/JlSection';
|
||||||
|
|
||||||
|
const commonTurnoutConsts = {
|
||||||
|
lineWidth: 5,
|
||||||
|
forkLenth: 20,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class TurnoutDraw<S extends GraphicState> extends GraphicDrawAssistant<
|
||||||
|
TurnoutTemplate<S>,
|
||||||
|
ITurnoutData
|
||||||
|
> {
|
||||||
|
turnout: JlTurnout;
|
||||||
|
constructor(app: IDrawApp, template: TurnoutTemplate<S>) {
|
||||||
|
super(app, template, 'sym_o_ramp_left', '道岔Turnout');
|
||||||
|
|
||||||
|
this.turnout = this.graphicTemplate.new();
|
||||||
|
this.container.addChild(this.turnout);
|
||||||
|
|
||||||
|
TurnoutPointsInteractionPlugin.init(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
bind(): void {
|
||||||
|
super.bind();
|
||||||
|
this.turnout.loadData(this.graphicTemplate.datas);
|
||||||
|
this.turnout.doRepaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
onLeftUp(e: FederatedMouseEvent): void {
|
||||||
|
this.turnout.position.copyFrom(this.toCanvasCoordinates(e.global));
|
||||||
|
this.createAndStore(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareData(data: ITurnoutData): boolean {
|
||||||
|
data.transform = this.turnout.saveTransform();
|
||||||
|
data.code = 'A000000';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
redraw(cp: Point): void {
|
||||||
|
this.turnout.position.copyFrom(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ForkHitArea implements IHitArea {
|
||||||
|
turnout: JlTurnout;
|
||||||
|
constructor(turnout: JlTurnout) {
|
||||||
|
this.turnout = turnout;
|
||||||
|
}
|
||||||
|
contains(x: number, y: number): boolean {
|
||||||
|
const intersectPointB = getForkPoint(
|
||||||
|
commonTurnoutConsts.forkLenth,
|
||||||
|
this.turnout.datas.pointB[0],
|
||||||
|
);
|
||||||
|
const intersectPointC = getForkPoint(
|
||||||
|
commonTurnoutConsts.forkLenth,
|
||||||
|
this.turnout.datas.pointC[0],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
linePoint(
|
||||||
|
intersectPointB,
|
||||||
|
{ x: 0, y: 0 },
|
||||||
|
{ x, y },
|
||||||
|
commonTurnoutConsts.lineWidth,
|
||||||
|
) ||
|
||||||
|
linePoint(
|
||||||
|
intersectPointC,
|
||||||
|
{ x: 0, y: 0 },
|
||||||
|
{ x, y },
|
||||||
|
commonTurnoutConsts.lineWidth,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TurnoutSectionHitArea implements IHitArea {
|
||||||
|
section: TurnoutSection;
|
||||||
|
constructor(section: TurnoutSection) {
|
||||||
|
this.section = section;
|
||||||
|
}
|
||||||
|
contains(x: number, y: number): boolean {
|
||||||
|
let points: IPointData[];
|
||||||
|
let start: IPointData;
|
||||||
|
switch (this.section.port) {
|
||||||
|
case DevicePort.A:
|
||||||
|
points = this.section.turnout.datas.pointA;
|
||||||
|
start = { x: 0, y: 0 };
|
||||||
|
break;
|
||||||
|
case DevicePort.B:
|
||||||
|
points = this.section.turnout.datas.pointB;
|
||||||
|
start = getForkPoint(commonTurnoutConsts.forkLenth, points[0]);
|
||||||
|
break;
|
||||||
|
case DevicePort.C:
|
||||||
|
points = this.section.turnout.datas.pointC;
|
||||||
|
start = getForkPoint(commonTurnoutConsts.forkLenth, points[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return polylinePoint(
|
||||||
|
[start, ...points],
|
||||||
|
{ x, y },
|
||||||
|
commonTurnoutConsts.lineWidth,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildAbsorbablePositions(turnout: JlTurnout): AbsorbablePosition[] {
|
||||||
|
const aps: AbsorbablePosition[] = [];
|
||||||
|
|
||||||
|
const sections = turnout.queryStore.queryByType<JlSection>(JlSection.Type);
|
||||||
|
sections.forEach((section) => {
|
||||||
|
const ps = new AbsorbablePoint(
|
||||||
|
section.localToCanvasPoint(section.getStartPoint()),
|
||||||
|
);
|
||||||
|
const pe = new AbsorbablePoint(
|
||||||
|
section.localToCanvasPoint(section.getEndPoint()),
|
||||||
|
);
|
||||||
|
aps.push(ps, pe); //区段端点
|
||||||
|
});
|
||||||
|
|
||||||
|
const turnouts = turnout.queryStore.queryByType<JlTurnout>(JlTurnout.Type);
|
||||||
|
turnouts.forEach((otherTurnout) => {
|
||||||
|
const {
|
||||||
|
pointA: [A],
|
||||||
|
pointB: [B],
|
||||||
|
pointC: [C],
|
||||||
|
} = otherTurnout.datas;
|
||||||
|
|
||||||
|
[A, B, C].forEach((p) => {
|
||||||
|
aps.push(
|
||||||
|
new AbsorbablePoint(otherTurnout.localToCanvasPoint(p)), //道岔端点
|
||||||
|
new AbsorbableLine(
|
||||||
|
otherTurnout.localToCanvasPoint({ x: -5 * p.x, y: -5 * p.y }),
|
||||||
|
otherTurnout.localToCanvasPoint({ x: 5 * p.x, y: 5 * p.y }),
|
||||||
|
), //道岔延长线
|
||||||
|
);
|
||||||
|
});
|
||||||
|
aps.push(
|
||||||
|
new AbsorbableLine(
|
||||||
|
otherTurnout.localToCanvasPoint({ x: 0, y: -500 }),
|
||||||
|
otherTurnout.localToCanvasPoint({ x: 0, y: 500 }),
|
||||||
|
), //岔心垂直线
|
||||||
|
new AbsorbableLine(
|
||||||
|
otherTurnout.localToCanvasPoint({ x: -500, y: 0 }),
|
||||||
|
otherTurnout.localToCanvasPoint({ x: 500, y: 0 }),
|
||||||
|
), //岔心水平线
|
||||||
|
new AbsorbableLine(
|
||||||
|
otherTurnout.localToCanvasPoint({ x: -500, y: 500 }),
|
||||||
|
otherTurnout.localToCanvasPoint({ x: 500, y: -500 }),
|
||||||
|
), //岔心/
|
||||||
|
new AbsorbableLine(
|
||||||
|
otherTurnout.localToCanvasPoint({ x: -500, y: -500 }),
|
||||||
|
otherTurnout.localToCanvasPoint({ x: 500, y: 500 }),
|
||||||
|
), //岔心\
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return aps;
|
||||||
|
}
|
||||||
|
|
||||||
|
type dragType = JlTurnout | JlSection;
|
||||||
|
class DragMoveAbsorbablePoint extends AbsorbablePoint {
|
||||||
|
moveTarget:
|
||||||
|
| {
|
||||||
|
position: IPointData;
|
||||||
|
portPos: IPointData[];
|
||||||
|
}
|
||||||
|
| undefined;
|
||||||
|
constructor(point: IPointData, absorbRange = 15) {
|
||||||
|
super(point, absorbRange);
|
||||||
|
}
|
||||||
|
tryAbsorb(...dragTargets: dragType[]): void {
|
||||||
|
const dragTarget = dragTargets[0];
|
||||||
|
if (dragTarget instanceof JlTurnout) {
|
||||||
|
if (this.moveTarget == undefined) {
|
||||||
|
const {
|
||||||
|
pointA: [A],
|
||||||
|
pointB: [B],
|
||||||
|
pointC: [C],
|
||||||
|
} = dragTarget.datas;
|
||||||
|
this.moveTarget = {
|
||||||
|
position: dragTarget.getGlobalPosition(),
|
||||||
|
portPos: [
|
||||||
|
dragTarget.localToCanvasPoint(A),
|
||||||
|
dragTarget.localToCanvasPoint(B),
|
||||||
|
dragTarget.localToCanvasPoint(C),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
pointA: [A],
|
||||||
|
pointB: [B],
|
||||||
|
pointC: [C],
|
||||||
|
} = dragTarget.datas;
|
||||||
|
[A, B, C].forEach((p, i) => {
|
||||||
|
const changePos = dragTarget.localToCanvasPoint(p);
|
||||||
|
if (
|
||||||
|
distance(this._point.x, this._point.y, changePos.x, changePos.y) <
|
||||||
|
this.absorbRange &&
|
||||||
|
this.moveTarget
|
||||||
|
) {
|
||||||
|
dragTarget.updatePositionByCanvasPosition(
|
||||||
|
new Point(
|
||||||
|
this.moveTarget.position.x +
|
||||||
|
this._point.x -
|
||||||
|
this.moveTarget.portPos[i].x,
|
||||||
|
this.moveTarget.position.y +
|
||||||
|
this._point.y -
|
||||||
|
this.moveTarget.portPos[i].y,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (this.moveTarget == undefined) {
|
||||||
|
this.moveTarget = {
|
||||||
|
position: dragTarget.getGlobalPosition(),
|
||||||
|
portPos: [
|
||||||
|
dragTarget.localToCanvasPoint(dragTarget.getStartPoint()),
|
||||||
|
dragTarget.localToCanvasPoint(dragTarget.getEndPoint()),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
dragTarget
|
||||||
|
.localToCanvasPoints(...dragTarget.datas.points)
|
||||||
|
.forEach((p, i) => {
|
||||||
|
if (
|
||||||
|
distance(this._point.x, this._point.y, p.x, p.y) <
|
||||||
|
this.absorbRange &&
|
||||||
|
this.moveTarget
|
||||||
|
) {
|
||||||
|
dragTarget.updatePositionByCanvasPosition(
|
||||||
|
new Point(
|
||||||
|
this.moveTarget.position.x +
|
||||||
|
this._point.x -
|
||||||
|
this.moveTarget.portPos[i].x,
|
||||||
|
this.moveTarget.position.y +
|
||||||
|
this._point.y -
|
||||||
|
this.moveTarget.portPos[i].y,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildDragMoveAbsorbablePositions(
|
||||||
|
target: dragType,
|
||||||
|
): AbsorbablePosition[] {
|
||||||
|
const aps: AbsorbablePosition[] = [];
|
||||||
|
|
||||||
|
const sections = target.queryStore.queryByType<JlSection>(JlSection.Type);
|
||||||
|
sections.forEach((section) => {
|
||||||
|
if (section.id !== target.id) {
|
||||||
|
section.localToCanvasPoints(...section.datas.points).forEach((p) => {
|
||||||
|
aps.push(new DragMoveAbsorbablePoint(p)); //区段端点
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const turnouts = target.queryStore.queryByType<JlTurnout>(JlTurnout.Type);
|
||||||
|
turnouts.forEach((otherTurnout) => {
|
||||||
|
if (otherTurnout.id !== target.id) {
|
||||||
|
const {
|
||||||
|
pointA: [A],
|
||||||
|
pointB: [B],
|
||||||
|
pointC: [C],
|
||||||
|
} = otherTurnout.datas;
|
||||||
|
[A, B, C].forEach((p) => {
|
||||||
|
aps.push(
|
||||||
|
new DragMoveAbsorbablePoint(otherTurnout.localToCanvasPoint(p)), //道岔端点
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return aps;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onEditPointCreate(turnout: JlTurnout, dp: DraggablePoint) {
|
||||||
|
dp.on('transformstart', (e: GraphicTransformEvent) => {
|
||||||
|
if (e.isShift()) {
|
||||||
|
turnout.getGraphicApp().setOptions({
|
||||||
|
absorbablePositions: buildAbsorbablePositions(turnout),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const addPointConfig: MenuItemOptions = { name: '添加路径点' };
|
||||||
|
const clearPointConfig: MenuItemOptions = { name: '清除路径点' };
|
||||||
|
|
||||||
|
const turnoutSectionEditMenu: ContextMenu = ContextMenu.init({
|
||||||
|
name: '道岔区段路径编辑',
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
items: [addPointConfig, clearPointConfig],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<JlTurnout> {
|
||||||
|
static Name = 'TurnoutPointsDrag';
|
||||||
|
static init(app: IDrawApp) {
|
||||||
|
return new TurnoutPointsInteractionPlugin(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(app: IGraphicApp) {
|
||||||
|
super(TurnoutPointsInteractionPlugin.Name, app);
|
||||||
|
app.registerMenu(turnoutSectionEditMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSectionContextMenu(e: FederatedMouseEvent, section: TurnoutSection) {
|
||||||
|
const p = section.turnout.screenToLocalPoint(e.global);
|
||||||
|
addPointConfig.handler = () => {
|
||||||
|
if (section.port === DevicePort.A) {
|
||||||
|
const { start } = getWaypointRangeIndex(
|
||||||
|
[{ x: 0, y: 0 }, ...section.turnout.datas.pointA],
|
||||||
|
false,
|
||||||
|
p,
|
||||||
|
commonTurnoutConsts.lineWidth,
|
||||||
|
);
|
||||||
|
const points = section.turnout.datas.pointA;
|
||||||
|
const ps = points.slice(0, start);
|
||||||
|
ps.push(new Point(p.x, p.y));
|
||||||
|
ps.push(...points.slice(start));
|
||||||
|
section.turnout.datas.pointA = ps;
|
||||||
|
}
|
||||||
|
if (section.port === DevicePort.B) {
|
||||||
|
const { start } = getWaypointRangeIndex(
|
||||||
|
[{ x: 0, y: 0 }, ...section.turnout.datas.pointB],
|
||||||
|
false,
|
||||||
|
p,
|
||||||
|
commonTurnoutConsts.lineWidth,
|
||||||
|
);
|
||||||
|
const points = section.turnout.datas.pointB;
|
||||||
|
const ps = points.slice(0, start);
|
||||||
|
ps.push(new Point(p.x, p.y));
|
||||||
|
ps.push(...points.slice(start));
|
||||||
|
section.turnout.datas.pointB = ps;
|
||||||
|
}
|
||||||
|
if (section.port === DevicePort.C) {
|
||||||
|
const { start } = getWaypointRangeIndex(
|
||||||
|
[{ x: 0, y: 0 }, ...section.turnout.datas.pointC],
|
||||||
|
false,
|
||||||
|
p,
|
||||||
|
commonTurnoutConsts.lineWidth,
|
||||||
|
);
|
||||||
|
const points = section.turnout.datas.pointC;
|
||||||
|
const ps = points.slice(0, start);
|
||||||
|
ps.push(new Point(p.x, p.y));
|
||||||
|
ps.push(...points.slice(start));
|
||||||
|
section.turnout.datas.pointC = ps;
|
||||||
|
}
|
||||||
|
this.onSelected(section.turnout);
|
||||||
|
};
|
||||||
|
clearPointConfig.handler = () => {
|
||||||
|
if (section.port === DevicePort.A)
|
||||||
|
section.turnout.datas.pointA = [
|
||||||
|
section.turnout.datas.pointA[section.turnout.datas.pointA.length - 1],
|
||||||
|
];
|
||||||
|
if (section.port === DevicePort.B)
|
||||||
|
section.turnout.datas.pointB = [
|
||||||
|
section.turnout.datas.pointB[section.turnout.datas.pointB.length - 1],
|
||||||
|
];
|
||||||
|
if (section.port === DevicePort.C)
|
||||||
|
section.turnout.datas.pointC = [
|
||||||
|
section.turnout.datas.pointC[section.turnout.datas.pointC.length - 1],
|
||||||
|
];
|
||||||
|
const tep = section.turnout.getAssistantAppend<TurnoutEditPlugin>(
|
||||||
|
TurnoutEditPlugin.Name,
|
||||||
|
);
|
||||||
|
if (tep) {
|
||||||
|
tep.reset();
|
||||||
|
}
|
||||||
|
section.turnout.repaint();
|
||||||
|
};
|
||||||
|
turnoutSectionEditMenu.open(e.global);
|
||||||
|
}
|
||||||
|
|
||||||
|
bind(g: JlTurnout): void {
|
||||||
|
g.graphics.fork.eventMode = 'static';
|
||||||
|
g.graphics.fork.cursor = 'pointer';
|
||||||
|
g.graphics.fork.hitArea = new ForkHitArea(g);
|
||||||
|
g.graphics.sections.forEach((sectionGraphic) => {
|
||||||
|
sectionGraphic.eventMode = 'static';
|
||||||
|
sectionGraphic.cursor = 'pointer';
|
||||||
|
sectionGraphic.hitArea = new TurnoutSectionHitArea(sectionGraphic);
|
||||||
|
sectionGraphic.on(
|
||||||
|
'rightclick',
|
||||||
|
(e) => this.onSectionContextMenu(e, sectionGraphic),
|
||||||
|
sectionGraphic,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
g.graphics.label.eventMode = 'static';
|
||||||
|
g.graphics.label.cursor = 'pointer';
|
||||||
|
g.graphics.label.draggable = true;
|
||||||
|
g.graphics.label.selectable = true;
|
||||||
|
g.graphics.label.name = 'label';
|
||||||
|
g.graphics.label.transformSave = true;
|
||||||
|
g.transformSave = true;
|
||||||
|
g.on('selected', this.onSelected, this);
|
||||||
|
g.on('unselected', this.onUnSelected, this);
|
||||||
|
g.on('transformstart', this.onDragMove, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
unbind(g: JlTurnout): void {
|
||||||
|
g.off('selected', this.onSelected, this);
|
||||||
|
g.off('unselected', this.onUnSelected, this);
|
||||||
|
g.graphics.sections.forEach((sectionGraphic) => {
|
||||||
|
sectionGraphic.off('rightclick');
|
||||||
|
});
|
||||||
|
g.off('transformstart', this.onDragMove, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelected(g: DisplayObject) {
|
||||||
|
const turnout = g as JlTurnout;
|
||||||
|
let tep = turnout.getAssistantAppend<TurnoutEditPlugin>(
|
||||||
|
TurnoutEditPlugin.Name,
|
||||||
|
);
|
||||||
|
if (!tep) {
|
||||||
|
tep = new TurnoutEditPlugin(turnout, { onEditPointCreate });
|
||||||
|
turnout.addAssistantAppend(tep);
|
||||||
|
}
|
||||||
|
tep.reset();
|
||||||
|
tep.showAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnSelected(g: DisplayObject) {
|
||||||
|
const turnout = g as JlTurnout;
|
||||||
|
const tep = turnout.getAssistantAppend<TurnoutEditPlugin>(
|
||||||
|
TurnoutEditPlugin.Name,
|
||||||
|
);
|
||||||
|
if (tep) {
|
||||||
|
tep.hideAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filter(...grahpics: JlGraphic[]): JlTurnout[] | undefined {
|
||||||
|
return grahpics.filter((g) => g.type == JlTurnout.Type) as JlTurnout[];
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragMove(e: GraphicTransformEvent) {
|
||||||
|
const turnout = e.target as JlTurnout;
|
||||||
|
this.app.setOptions({
|
||||||
|
absorbablePositions: buildDragMoveAbsorbablePositions(turnout),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type onTurnoutEditPointCreate = (
|
||||||
|
turnout: JlTurnout,
|
||||||
|
dp: DraggablePoint,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
export interface ITurnoutEditOptions {
|
||||||
|
onEditPointCreate?: onTurnoutEditPointCreate;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TurnoutEditPlugin extends GraphicEditPlugin<JlTurnout> {
|
||||||
|
static Name = 'TurnoutEdit';
|
||||||
|
options: ITurnoutEditOptions;
|
||||||
|
editPoints: DraggablePoint[][] = [[], [], []];
|
||||||
|
labels: VectorText[] = [];
|
||||||
|
|
||||||
|
constructor(graphic: JlTurnout, options?: ITurnoutEditOptions) {
|
||||||
|
super(graphic);
|
||||||
|
this.name = TurnoutEditPlugin.Name;
|
||||||
|
this.options = Object.assign({}, options);
|
||||||
|
this.initEditPoints();
|
||||||
|
}
|
||||||
|
reset(): void {
|
||||||
|
this.destoryEditPoints();
|
||||||
|
this.removeChildren();
|
||||||
|
this.initEditPoints();
|
||||||
|
}
|
||||||
|
hideAll(): void {
|
||||||
|
super.hideAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
initEditPoints() {
|
||||||
|
const cpA = this.graphic.localToCanvasPoints(...this.graphic.datas.pointA);
|
||||||
|
const cpB = this.graphic.localToCanvasPoints(...this.graphic.datas.pointB);
|
||||||
|
const cpC = this.graphic.localToCanvasPoints(...this.graphic.datas.pointC);
|
||||||
|
const cpMap: Map<Point[], IPointData[]> = new Map([
|
||||||
|
[cpA, this.graphic.datas.pointA],
|
||||||
|
[cpB, this.graphic.datas.pointB],
|
||||||
|
[cpC, this.graphic.datas.pointC],
|
||||||
|
]);
|
||||||
|
Array.from(cpMap.entries()).forEach(([cpDatas, dataPoints], i) => {
|
||||||
|
cpDatas.forEach((cpData, j) => {
|
||||||
|
const dp = new DraggablePoint(cpData);
|
||||||
|
dp.on('transforming', () => {
|
||||||
|
const localPoint = this.graphic.canvasToLocalPoint(dp.position);
|
||||||
|
dataPoints[j].x = localPoint.x;
|
||||||
|
dataPoints[j].y = localPoint.y;
|
||||||
|
|
||||||
|
this.graphic.repaint();
|
||||||
|
});
|
||||||
|
if (this.options.onEditPointCreate) {
|
||||||
|
this.options.onEditPointCreate(this.graphic, dp);
|
||||||
|
}
|
||||||
|
this.editPoints[i].push(dp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.editPoints.forEach((cps) => {
|
||||||
|
this.addChild(...cps);
|
||||||
|
});
|
||||||
|
this.labels = ['A', 'B', 'C'].map((str) => {
|
||||||
|
const vc = new VectorText(str, { fill: AppConsts.assistantElementColor });
|
||||||
|
vc.setVectorFontSize(14);
|
||||||
|
vc.anchor.set(0.5);
|
||||||
|
return vc;
|
||||||
|
});
|
||||||
|
this.addChild(...this.labels);
|
||||||
|
}
|
||||||
|
|
||||||
|
destoryEditPoints() {
|
||||||
|
this.editPoints.forEach((dps) => {
|
||||||
|
dps.forEach((dp) => {
|
||||||
|
dp.off('transforming');
|
||||||
|
dp.destroy();
|
||||||
|
this.removeChild(dp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.editPoints = [[], [], []];
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEditedPointsPosition() {
|
||||||
|
const cpA = this.graphic.localToCanvasPoints(...this.graphic.datas.pointA);
|
||||||
|
const cpB = this.graphic.localToCanvasPoints(...this.graphic.datas.pointB);
|
||||||
|
const cpC = this.graphic.localToCanvasPoints(...this.graphic.datas.pointC);
|
||||||
|
[cpA, cpB, cpC].forEach((cps, i) => {
|
||||||
|
cps.forEach((cp, j) => {
|
||||||
|
this.editPoints[i][j].position.copyFrom(cp);
|
||||||
|
if (j === cps.length - 1) {
|
||||||
|
this.labels[i].position.copyFrom({ x: cp.x, y: cp.y + 12 });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
38
src/packages/Turnout/common/TurnoutTemplate.ts
Normal file
38
src/packages/Turnout/common/TurnoutTemplate.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { GraphicState, JlGraphicTemplate } from 'jl-graphic';
|
||||||
|
import { JlTurnout } from './JlTurnout';
|
||||||
|
import { ITurnoutData } from './TurnoutConfig';
|
||||||
|
import { StyleType } from 'common/common';
|
||||||
|
import { GPTurnout } from '../GPTurnout';
|
||||||
|
import { THTurnout } from '../THTurnout';
|
||||||
|
|
||||||
|
export class TurnoutTemplate<
|
||||||
|
S extends GraphicState,
|
||||||
|
> extends JlGraphicTemplate<JlTurnout> {
|
||||||
|
styleType: StyleType;
|
||||||
|
constructor(
|
||||||
|
dataTemplate: ITurnoutData,
|
||||||
|
stateTemplate: S,
|
||||||
|
styleType: StyleType,
|
||||||
|
) {
|
||||||
|
super(JlTurnout.Type, {
|
||||||
|
dataTemplate,
|
||||||
|
stateTemplate,
|
||||||
|
});
|
||||||
|
this.styleType = styleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
new() {
|
||||||
|
let turnout: JlTurnout;
|
||||||
|
switch (this.styleType) {
|
||||||
|
case StyleType.GP:
|
||||||
|
turnout = new GPTurnout();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
turnout = new THTurnout();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
turnout.loadData(this.datas);
|
||||||
|
turnout.loadState(this.states);
|
||||||
|
return turnout;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user