From 218cae4c5cf47aa9aad70b19393fbd0e3fc54825 Mon Sep 17 00:00:00 2001 From: walker Date: Sun, 25 Jun 2023 15:04:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=90=B8=E9=99=84bug-?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=9D=90=E6=A0=87=E5=88=B0=E7=94=BB=E5=B8=83?= =?UTF-8?q?=E5=9D=90=E6=A0=87=E7=A9=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/graphics/signal/SignalDrawAssistant.ts | 34 +++++++++- src/jlgraphic/core/JlGraphic.ts | 17 +++++ src/jlgraphic/global.d.ts | 70 ++++++++++++++++++--- src/jlgraphic/graphic/AbsorbablePosition.ts | 49 +++++++++++---- 4 files changed, 148 insertions(+), 22 deletions(-) diff --git a/src/graphics/signal/SignalDrawAssistant.ts b/src/graphics/signal/SignalDrawAssistant.ts index 043c51f..c119cdc 100644 --- a/src/graphics/signal/SignalDrawAssistant.ts +++ b/src/graphics/signal/SignalDrawAssistant.ts @@ -1,11 +1,16 @@ import { FederatedPointerEvent, Point } from 'pixi.js'; import { + AbsorbableLine, + AbsorbablePosition, + GraphicApp, GraphicDrawAssistant, GraphicInteractionPlugin, + GraphicTransformEvent, JlDrawApp, JlGraphic, } from 'src/jlgraphic'; import { ISignalData, Signal, SignalTemplate } from './Signal'; +import { IscsFan } from '../iscs-fan/IscsFan'; export interface ISignalDrawOptions { newData: () => ISignalData; @@ -82,7 +87,19 @@ export class signalInteraction extends GraphicInteractionPlugin { g.codeGraph.scalable = true; g.codeGraph.transformSave = true; g.codeGraph.eventMode = 'static'; - // g.codeGraph.on('transformend', this.onScaleDragEnd, this); + g.codeGraph.on('transformstart', (e: GraphicTransformEvent) => { + if (e.isShift()) { + console.log( + '信号机画布坐标', + e.target.position, + e.target.getPositionOnCanvas() + ); + const app = g.getGraphicApp(); + app.setOptions({ + absorbablePositions: buildAbsorbablePositions(app), + }); + } + }); } // onScaleDragEnd() { // console.log('-----------------'); @@ -99,3 +116,18 @@ export class signalInteraction extends GraphicInteractionPlugin { g.codeGraph.eventMode = 'none'; } } +function buildAbsorbablePositions(app: GraphicApp): AbsorbablePosition[] { + const canvas = app.canvas; + const store = app.queryStore; + const aps: AbsorbablePosition[] = []; + store.queryByType(IscsFan.Type).forEach((fan) => { + const p = fan.position; + aps.push( + new AbsorbableLine(new Point(0, p.y), new Point(canvas.width, p.y)) + ); + aps.push( + new AbsorbableLine(new Point(p.x, 0), new Point(p.x, canvas.height)) + ); + }); + return aps; +} diff --git a/src/jlgraphic/core/JlGraphic.ts b/src/jlgraphic/core/JlGraphic.ts index c4c0d91..7ed967a 100644 --- a/src/jlgraphic/core/JlGraphic.ts +++ b/src/jlgraphic/core/JlGraphic.ts @@ -148,6 +148,23 @@ DisplayObject.prototype.getAllParentScaled = }); return scaled; }; +DisplayObject.prototype.getPositionOnCanvas = + function getPositionOnCanvas(): Point { + if (this.parent.isCanvas()) { + return this.position; + } else { + return this.parent.localToCanvasPoint(this.position); + } + }; +DisplayObject.prototype.updatePositionByCanvasPosition = + function updatePositionByCanvasPosition(p: IPointData): void { + if (this.parent.isCanvas()) { + this.position.copyFrom(p); + } else { + const localPosition = this.parent.canvasToLocalPoint(p); + this.position.copyFrom(localPosition); + } + }; DisplayObject.prototype.saveTransform = function saveTransform() { return GraphicTransform.fromObject(this); }; diff --git a/src/jlgraphic/global.d.ts b/src/jlgraphic/global.d.ts index df5fa49..a70a5f9 100644 --- a/src/jlgraphic/global.d.ts +++ b/src/jlgraphic/global.d.ts @@ -60,9 +60,28 @@ declare namespace GlobalMixins { _rotatable: boolean; // 是否可旋转 rotatable: boolean; worldAngle: number; // 世界角度,(-180, 180] + /** + * 获取所有父级元素叠加缩放 + */ getAllParentScaled(): PointType; - saveTransform(): GraphicTransform; // 保存变换 - loadTransform(transform: GraphicTransform): void; // 加载变换 + /** + * 获取位置在画布的坐标 + */ + getPositionOnCanvas(): PointType; + /** + * 通过画布坐标更新位置 + * @param p 画布坐标 + */ + updatePositionByCanvasPosition(p: IPointData): void; + /** + * 保存变换数据 + */ + saveTransform(): GraphicTransform; + /** + * 加载变换 + * @param transform 变换数据 + */ + loadTransform(transform: GraphicTransform): void; isChild(obj: DisplayObject): boolean; // 是否子元素 isParent(obj: DisplayObject): boolean; // 是否父元素 isAssistantAppend(): boolean; // 是否辅助附加图形 @@ -83,14 +102,45 @@ declare namespace GlobalMixins { isCanvas(): boolean; // 是否画布对象 getViewport(): Viewport; // 获取视口 getGraphicApp(): GraphicApp; // 获取图形app - localToCanvasPoint(p: IPointData): PointType; // 图形本地坐标转为画布坐标 - localToCanvasPoints(...points: IPointData[]): PointType[]; // 批量转换 - canvasToLocalPoint(p: IPointData): PointType; // 画布坐标转为图形本地坐标 - canvasToLocalPoints(...points: IPointData[]): PointType[]; // 批量转换 - - localToScreenPoint(p: IPointData): PointType; // 本地坐标转为屏幕坐标 - localToScreenPoints(...points: IPointData[]): PointType[]; // 批量 - screenToLocalPoint(p: IPointData): PointType; // 屏幕坐标转为本地坐标 + /** + * 图形本地坐标转为画布坐标 + * @param p 图形本地坐标 + */ + localToCanvasPoint(p: IPointData): PointType; + /** + * 批量转换图形本地坐标为画布坐标 + * @param points 图形本地坐标 + */ + localToCanvasPoints(...points: IPointData[]): PointType[]; + /** + * 画布坐标转为图形本地坐标 + * @param p 画布坐标 + */ + canvasToLocalPoint(p: IPointData): PointType; + /** + * 批量转换画布坐标为图形本地坐标 + * @param points 画布坐标 + */ + canvasToLocalPoints(...points: IPointData[]): PointType[]; + /** + * 本地坐标转为屏幕坐标 + * @param p 本地坐标 + */ + localToScreenPoint(p: IPointData): PointType; + /** + * 批量转换本地坐标为屏幕坐标 + * @param points 本地坐标 + */ + localToScreenPoints(...points: IPointData[]): PointType[]; + /** + * 屏幕坐标转为本地坐标 + * @param p 屏幕坐标 + */ + screenToLocalPoint(p: IPointData): PointType; + /** + * 批量转换屏幕坐标为本地坐标 + * @param points 屏幕坐标 + */ screenToLocalPoints(...points: IPointData[]): PointType[]; // 批量 localBoundsToCanvasPoints(): PointType[]; // 本地包围框转为多边形点坐标 diff --git a/src/jlgraphic/graphic/AbsorbablePosition.ts b/src/jlgraphic/graphic/AbsorbablePosition.ts index 0d5405f..b3a7acf 100644 --- a/src/jlgraphic/graphic/AbsorbablePosition.ts +++ b/src/jlgraphic/graphic/AbsorbablePosition.ts @@ -72,6 +72,11 @@ export default class AbsorbablePoint absorbRange: number; scaledListenerOn = false; + /** + * + * @param point 画布坐标 + * @param absorbRange + */ constructor(point: IPointData, absorbRange = 10) { super(AbsorbablePointGraphic.geometry); this._point = new Point(point.x, point.y); @@ -98,11 +103,16 @@ export default class AbsorbablePoint tryAbsorb(...objs: DisplayObject[]): void { for (let i = 0; i < objs.length; i++) { const obj = objs[i]; + const canvasPosition = obj.getPositionOnCanvas(); if ( - distance(this._point.x, this._point.y, obj.position.x, obj.position.y) < - this.absorbRange + distance( + this._point.x, + this._point.y, + canvasPosition.x, + canvasPosition.y + ) < this.absorbRange ) { - obj.position.copyFrom(this._point); + obj.updatePositionByCanvasPosition(this._point); } } } @@ -122,6 +132,12 @@ export class AbsorbableLine extends Graphics implements AbsorbablePosition { absorbRange: number; _color = '#E77E0E'; + /** + * + * @param p1 画布坐标 + * @param p2 画布坐标 + * @param absorbRange + */ constructor(p1: IPointData, p2: IPointData, absorbRange = 20) { super(); this.p1 = new Point(p1.x, p1.y); @@ -155,10 +171,14 @@ export class AbsorbableLine extends Graphics implements AbsorbablePosition { tryAbsorb(...objs: DisplayObject[]): void { for (let i = 0; i < objs.length; i++) { const obj = objs[i]; - const p = obj.position.clone(); - if (linePoint(this.p1, this.p2, p, this.absorbRange, true)) { - const fp = calculateFootPointFromPointToLine(this.p1, this.p2, p); - obj.position.copyFrom(fp); + const canvasPosition = obj.getPositionOnCanvas(); + if (linePoint(this.p1, this.p2, canvasPosition, this.absorbRange, true)) { + const fp = calculateFootPointFromPointToLine( + this.p1, + this.p2, + canvasPosition + ); + obj.updatePositionByCanvasPosition(fp); } } } @@ -173,6 +193,12 @@ export class AbsorbableCircle extends Graphics implements AbsorbablePosition { radius: number; _color = '#E77E0E'; + /** + * + * @param p 画布坐标 + * @param radius + * @param absorbRange + */ constructor(p: IPointData, radius: number, absorbRange = 10) { super(); this.p0 = new Point(p.x, p.y); @@ -202,11 +228,12 @@ export class AbsorbableCircle extends Graphics implements AbsorbablePosition { tryAbsorb(...objs: DisplayObject[]): void { for (let i = 0; i < objs.length; i++) { const obj = objs[i]; + const canvasPosition = obj.getPositionOnCanvas(); const len = distance( this.p0.x, this.p0.y, - obj.position.x, - obj.position.y + canvasPosition.x, + canvasPosition.y ); if ( len > this.radius - this.absorbRange && @@ -216,9 +243,9 @@ export class AbsorbableCircle extends Graphics implements AbsorbablePosition { const p = calculateIntersectionPointOfCircleAndPoint( this.p0, this.radius, - obj.position + canvasPosition ); - obj.position.copyFrom(p); + obj.updatePositionByCanvasPosition(p); } } }