Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(draw): add display shape for flowchart #WIK-15411 #865

Merged
merged 1 commit into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/bright-turkeys-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@plait/draw': minor
---

add display shape for flowchart
3 changes: 2 additions & 1 deletion packages/draw/src/constants/geometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ export const DefaultFlowchartPropertyMap = {
[FlowchartSymbols.internalStorage]: DefaultInternalStorageProperty,
[FlowchartSymbols.noteCurlyLeft]: DefaultNoteProperty,
[FlowchartSymbols.noteCurlyRight]: DefaultNoteProperty,
[FlowchartSymbols.noteSquare]: DefaultNoteProperty
[FlowchartSymbols.noteSquare]: DefaultNoteProperty,
[FlowchartSymbols.display]: DefaultFlowchartProperty
};

export const LINE_HIT_GEOMETRY_BUFFER = 10;
Expand Down
104 changes: 104 additions & 0 deletions packages/draw/src/engines/flowchart/display.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {
PlaitBoard,
Point,
PointOfRectangle,
RectangleClient,
getEllipseTangentSlope,
getNearestPointBetweenPointAndEllipse,
getNearestPointBetweenPointAndSegments,
getVectorFromPointAndSlope,
isPointInEllipse,
isPointInPolygon,
setStrokeLinecap
} from '@plait/core';
import { PlaitGeometry, ShapeEngine } from '../../interfaces';
import { Options } from 'roughjs/bin/core';
import { getStrokeWidthByElement } from '../../utils';

export const getDisplayPoints = (rectangle: RectangleClient): Point[] => {
return [
[rectangle.x, rectangle.y + rectangle.height / 2],
[rectangle.x + rectangle.width * 0.15, rectangle.y],
[rectangle.x + rectangle.width, rectangle.y],
[rectangle.x + rectangle.width, rectangle.y + rectangle.height],
[rectangle.x + rectangle.width * 0.15, rectangle.y + rectangle.height]
];
};

export const DisplayEngine: ShapeEngine = {
draw(board: PlaitBoard, rectangle: RectangleClient, options: Options) {
const rs = PlaitBoard.getRoughSVG(board);
const shape = rs.path(
`M${rectangle.x + rectangle.width * 0.15} ${rectangle.y}
H${rectangle.x + rectangle.width - rectangle.width * 0.1}
A ${rectangle.width * 0.1} ${rectangle.height / 2}, 0, 0, 1,${rectangle.x +
rectangle.width -
rectangle.width * 0.1} ${rectangle.y + rectangle.height}
H${rectangle.x + rectangle.width * 0.15}
L${rectangle.x} ${rectangle.y + rectangle.height / 2}
Z
`,
{ ...options, fillStyle: 'solid' }
);
setStrokeLinecap(shape, 'round');

return shape;
},
isInsidePoint(rectangle: RectangleClient, point: Point) {
const polygonPoints: Point[] = [
[rectangle.x, rectangle.y + rectangle.height / 2],
[rectangle.x + rectangle.width * 0.15, rectangle.y],
[rectangle.x + rectangle.width - rectangle.width * 0.1, rectangle.y],
[rectangle.x + rectangle.width - rectangle.width * 0.1, rectangle.y + rectangle.height],
[rectangle.x + rectangle.width * 0.15, rectangle.y + rectangle.height]
];
const isInPolygon = isPointInPolygon(point, polygonPoints);
const isInEllipse = isPointInEllipse(
point,
[rectangle.x + rectangle.width - rectangle.width * 0.1, rectangle.y + rectangle.height / 2],
rectangle.width * 0.1,
rectangle.height / 2
);
return isInPolygon || isInEllipse;
},
getCornerPoints(rectangle: RectangleClient) {
return RectangleClient.getCornerPoints(rectangle);
},
getNearestPoint(rectangle: RectangleClient, point: Point) {
const nearestPoint = getNearestPointBetweenPointAndSegments(point, getDisplayPoints(rectangle));
if (nearestPoint[0] > rectangle.x + rectangle.width - rectangle.width * 0.1) {
return getNearestPointBetweenPointAndEllipse(
point,
[rectangle.x + rectangle.width - rectangle.width * 0.1, rectangle.y + rectangle.height / 2],
rectangle.width * 0.1,
rectangle.height / 2
);
}
return nearestPoint;
},
getTangentVectorByConnectionPoint(rectangle: RectangleClient, pointOfRectangle: PointOfRectangle) {
const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
const centerPoint: Point = [rectangle.x + rectangle.width - rectangle.width * 0.1, rectangle.y + rectangle.height / 2];
const point = [connectionPoint[0] - centerPoint[0], -(connectionPoint[1] - centerPoint[1])];
const a = rectangle.width * 0.1;
const b = rectangle.height / 2;
const slope = getEllipseTangentSlope(point[0], point[1], a, b) as any;
return getVectorFromPointAndSlope(point[0], point[1], slope);
},

getConnectorPoints(rectangle: RectangleClient) {
return RectangleClient.getEdgeCenterPoints(rectangle);
},
getTextRectangle: (element: PlaitGeometry) => {
const elementRectangle = RectangleClient.getRectangleByPoints(element.points!);
const strokeWidth = getStrokeWidthByElement(element);
const height = element.textHeight;
const width = elementRectangle.width - strokeWidth * 2 - elementRectangle.width * 0.25;
return {
width: width > 0 ? width : 0,
height: height,
x: elementRectangle.x + strokeWidth + elementRectangle.width * 0.15,
y: elementRectangle.y + (elementRectangle.height - height) / 2
};
}
};
4 changes: 3 additions & 1 deletion packages/draw/src/engines/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { InternalStorageEngine } from './flowchart/internal-storage';
import { NoteCurlyLeftEngine } from './flowchart/note-curly-left';
import { NoteCurlyRightEngine } from './flowchart/note-curly-right';
import { NoteSquareEngine } from './flowchart/note-square';
import { DisplayEngine } from './flowchart/display';
import { TableEngine } from './table/table';

export const ShapeEngineMap: Record<GeometryShapes, ShapeEngine> = {
Expand Down Expand Up @@ -85,9 +86,10 @@ export const ShapeEngineMap: Record<GeometryShapes, ShapeEngine> = {
[FlowchartSymbols.noteCurlyLeft]: NoteCurlyLeftEngine,
[FlowchartSymbols.noteCurlyRight]: NoteCurlyRightEngine,
[FlowchartSymbols.noteSquare]: NoteSquareEngine,
[FlowchartSymbols.display]: DisplayEngine,
[SwimlaneSymbols.swimlaneHorizontal]: TableEngine,
[SwimlaneSymbols.swimlaneVertical]: TableEngine,
[TableSymbols.table]: TableEngine,
[TableSymbols.table]: TableEngine
};

export const getEngine = (shape: GeometryShapes) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/draw/src/interfaces/geometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ export enum FlowchartSymbols {
internalStorage = 'internalStorage',
noteCurlyRight = 'noteCurlyRight',
noteCurlyLeft = 'noteCurlyLeft',
noteSquare = 'noteSquare'
noteSquare = 'noteSquare',
display = 'display'
}

export enum TableSymbols {
Expand Down
28 changes: 28 additions & 0 deletions src/app/components/main-toolbar/main-toolbar.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,14 @@
<ng-template [ngTemplateOutlet]="summingJunction"></ng-template>
</a>

<a
class="action-item"
[ngClass]="{ active: isPointer(FlowchartSymbols.display) }"
(mousedown)="setPointer($event, FlowchartSymbols.display)"
>
<ng-template [ngTemplateOutlet]="display"></ng-template>
</a>

<a
class="action-item"
[ngClass]="{ active: isPointer(FlowchartSymbols.offPage) }"
Expand Down Expand Up @@ -1147,6 +1155,26 @@
</svg>
</ng-template>

<ng-template #display>
<svg
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<title>1.Base基础/1.icon图标/11.editor/ 流程图/显示</title>
<g id="1.Base基础/1.icon图标/11.editor/-流程图/显示" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path
d="M11.5,3 C13.9852814,3 16,5.23857625 16,8 C16,10.7614237 13.9852814,13 11.5,13 L3.26519621,13 C3.09934121,13 2.94428,12.9086186 2.85125276,12.7560528 L0,8.0799656 L2.85190553,3.25077161 C2.94433029,3.09426675 3.10147391,3 3.26994436,3 L11.5,3 Z M1.442,8.06777778 L3.636,11.6666667 L11.5,11.6666667 C13.2596935,11.6666667 14.6976959,10.1363074 14.7947761,8.208068 L14.8,8 C14.8,5.97495592 13.3225397,4.33333333 11.5,4.33333333 L3.648,4.33333333 L1.442,8.06777778 Z"
id="形状结合"
fill="#999999"
></path>
</g>
</svg>
</ng-template>

<ng-template #terminal>
<svg
xmlns="http://www.w3.org/2000/svg"
Expand Down
Loading