-
Notifications
You must be signed in to change notification settings - Fork 17
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): support draw line for element with angle #WIK-14850 #785
Changes from 2 commits
ae1b74f
695a776
b403079
7fd0fc4
2e24bc2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@plait/draw': minor | ||
--- | ||
|
||
support draw line for element with angle |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,16 @@ | ||
import { CursorClass, PlaitBoard, PlaitElement, RgbaToHEX, drawCircle, isSelectionMoving, toHostPoint, toViewBoxPoint } from '@plait/core'; | ||
import { | ||
CursorClass, | ||
PlaitBoard, | ||
PlaitElement, | ||
RectangleClient, | ||
RgbaToHEX, | ||
drawCircle, | ||
isSelectionMoving, | ||
rotatePoints, | ||
setAngleForG, | ||
toHostPoint, | ||
toViewBoxPoint | ||
} from '@plait/core'; | ||
import { PlaitDrawElement } from '../interfaces'; | ||
import { getAutoCompletePoints, getHitIndexOfAutoCompletePoint, getSelectedDrawElements } from '../utils'; | ||
import { GeometryComponent } from '../geometry.component'; | ||
|
@@ -15,8 +27,13 @@ export const withLineAutoCompleteReaction = (board: PlaitBoard) => { | |
const targetElement = selectedElements.length === 1 && selectedElements[0]; | ||
const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y)); | ||
if (!PlaitBoard.isReadonly(board) && !isSelectionMoving(board) && targetElement && PlaitDrawElement.isShape(targetElement)) { | ||
const [rotatedMovingPoint] = rotatePoints( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 验证 hasValidAngle |
||
[movingPoint], | ||
RectangleClient.getCenterPoint(board.getRectangle(targetElement)!), | ||
-targetElement.angle | ||
); | ||
const points = getAutoCompletePoints(targetElement); | ||
const hitIndex = getHitIndexOfAutoCompletePoint(movingPoint, points); | ||
const hitIndex = getHitIndexOfAutoCompletePoint(rotatedMovingPoint, points); | ||
const hitPoint = points[hitIndex]; | ||
const component = PlaitElement.getComponent(targetElement) as GeometryComponent; | ||
component.lineAutoCompleteGenerator!.recoverAutoCompleteG(); | ||
|
@@ -29,6 +46,7 @@ export const withLineAutoCompleteReaction = (board: PlaitBoard) => { | |
}); | ||
PlaitBoard.getElementActiveHost(board).append(reactionG); | ||
PlaitBoard.getBoardContainer(board).classList.add(CursorClass.crosshair); | ||
setAngleForG(reactionG, RectangleClient.getCenterPoint(board.getRectangle(targetElement)!), targetElement.angle); | ||
} | ||
} | ||
pointerMove(event); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,8 +9,10 @@ import { | |
Transforms, | ||
addSelectedElement, | ||
clearSelectedElement, | ||
createDebugGenerator, | ||
createG, | ||
distanceBetweenPointAndPoint, | ||
rotatePoints, | ||
temporaryDisableSelection, | ||
toHostPoint, | ||
toViewBoxPoint | ||
|
@@ -42,7 +44,12 @@ export const withLineAutoComplete = (board: PlaitBoard) => { | |
const clickPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y)); | ||
if (!PlaitBoard.isReadonly(board) && targetElement && PlaitDrawElement.isShape(targetElement)) { | ||
const points = getAutoCompletePoints(targetElement); | ||
const index = getHitIndexOfAutoCompletePoint(clickPoint, points); | ||
const [rotatedClickPoint] = rotatePoints( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hasValidAngle |
||
[clickPoint], | ||
RectangleClient.getCenterPoint(board.getRectangle(targetElement)!), | ||
-targetElement.angle | ||
); | ||
const index = getHitIndexOfAutoCompletePoint(rotatedClickPoint, points); | ||
const hitPoint = points[index]; | ||
if (hitPoint) { | ||
temporaryDisableSelection(board as PlaitOptionsBoard); | ||
|
@@ -59,7 +66,12 @@ export const withLineAutoComplete = (board: PlaitBoard) => { | |
lineShapeG = createG(); | ||
let movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y)); | ||
if (startPoint && sourceElement) { | ||
const distance = distanceBetweenPointAndPoint(...movingPoint, ...startPoint); | ||
const [rotatedStartPoint] = rotatePoints( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hasValidAngle |
||
[startPoint], | ||
RectangleClient.getCenterPoint(board.getRectangle(sourceElement)!), | ||
sourceElement.angle | ||
); | ||
const distance = distanceBetweenPointAndPoint(...movingPoint, ...rotatedStartPoint); | ||
if (distance > PRESS_AND_MOVE_BUFFER) { | ||
const rectangle = RectangleClient.getRectangleByPoints(sourceElement.points); | ||
const shape = getShape(sourceElement); | ||
|
@@ -69,6 +81,10 @@ export const withLineAutoComplete = (board: PlaitBoard) => { | |
const crossingPoint = engine.getNearestCrossingPoint(rectangle, startPoint); | ||
sourcePoint = crossingPoint; | ||
} | ||
|
||
if (sourceElement.angle) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hasValidAngle |
||
sourcePoint = rotatePoints([sourcePoint], RectangleClient.getCenterPoint(rectangle), sourceElement.angle)[0]; | ||
} | ||
temporaryElement = handleLineCreating(board, LineShape.elbow, sourcePoint, movingPoint, sourceElement, lineShapeG); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,8 @@ import { | |
RectangleClient, | ||
SELECTION_BORDER_COLOR, | ||
drawCircle, | ||
rotatePoints, | ||
setAngleForG, | ||
toHostPoint, | ||
toViewBoxPoint | ||
} from '@plait/core'; | ||
|
@@ -37,9 +39,10 @@ export const withLineBoundReaction = (board: PlaitBoard) => { | |
if (isLinePointer || isLineResizing) { | ||
const hitElement = getHitOutlineGeometry(board, movingPoint, -4); | ||
if (hitElement) { | ||
boundShapeG = drawBoundMask(board, hitElement); | ||
let nearestPoint = getNearestPoint(hitElement, movingPoint); | ||
const rectangle = RectangleClient.getRectangleByPoints(hitElement.points); | ||
boundShapeG = drawBoundMask(board, hitElement); | ||
const [rotatedMovingPoint] = rotatePoints([movingPoint], RectangleClient.getCenterPoint(rectangle), -hitElement.angle); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hasValidAngle |
||
let nearestPoint = getNearestPoint(hitElement, rotatedMovingPoint); | ||
const activeRectangle = RectangleClient.inflate(rectangle, ACTIVE_STROKE_WIDTH); | ||
const hitConnector = getHitConnectorPoint(nearestPoint, hitElement, activeRectangle); | ||
nearestPoint = hitConnector ? hitConnector : nearestPoint; | ||
|
@@ -51,6 +54,9 @@ export const withLineBoundReaction = (board: PlaitBoard) => { | |
}); | ||
boundShapeG.appendChild(circleG); | ||
PlaitBoard.getElementActiveHost(board).append(boundShapeG); | ||
if (hitElement.angle) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hasValidAngle |
||
setAngleForG(boundShapeG, RectangleClient.getCenterPoint(rectangle), hitElement.angle); | ||
} | ||
} | ||
} | ||
pointerMove(event); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { Path, PlaitBoard, PlaitNode, Point } from '@plait/core'; | ||
import { Path, PlaitBoard, PlaitNode, Point, RectangleClient, rotatePoints } from '@plait/core'; | ||
import { ResizeRef, ResizeState, WithResizeOptions, isSourceAndTargetIntersect, simplifyOrthogonalPoints, withResize } from '@plait/common'; | ||
import { getSelectedLineElements } from '../utils/selected'; | ||
import { getHitLineResizeHandleRef, LineResizeHandle } from '../utils/position/line'; | ||
|
@@ -80,7 +80,13 @@ export const withLineResize = (board: PlaitBoard) => { | |
const object = resizeRef.handle === LineResizeHandle.source ? source : target; | ||
points[handleIndex] = resizeState.endPoint; | ||
if (hitElement) { | ||
object.connection = getConnectionByNearestPoint(board, resizeState.endPoint, hitElement); | ||
const [rotatedEndPoint] = rotatePoints( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hasValidAngle |
||
[resizeState.endPoint], | ||
RectangleClient.getCenterPoint(board.getRectangle(hitElement)!), | ||
-hitElement.angle | ||
); | ||
|
||
object.connection = getConnectionByNearestPoint(board, rotatedEndPoint, hitElement); | ||
object.boundId = hitElement.id; | ||
} else { | ||
object.connection = undefined; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { Point, PlaitBoard, getElementById, RectangleClient, Vector } from '@plait/core'; | ||
import { Point, PlaitBoard, getElementById, RectangleClient, Vector, rotatePoints } from '@plait/core'; | ||
import { | ||
getPoints, | ||
getPointByVectorComponent, | ||
|
@@ -12,6 +12,8 @@ import { createGeometryElement } from '../geometry'; | |
import { getStrokeWidthByElement } from '../style/stroke'; | ||
import { getElbowLineRouteOptions, getLineHandleRefPair } from './line-common'; | ||
import { getMidKeyPoints, getMirrorDataPoints, hasIllegalElbowPoint } from './line-resize'; | ||
import { getShape } from '../shape'; | ||
import { getEngine } from '../../engines'; | ||
|
||
export const getElbowPoints = (board: PlaitBoard, element: PlaitLine) => { | ||
const handleRefPair = getLineHandleRefPair(board, element); | ||
|
@@ -40,7 +42,6 @@ export const getElbowPoints = (board: PlaitBoard, element: PlaitLine) => { | |
if (hasIllegalElbowPoint(midDataPoints)) { | ||
return simplifyOrthogonalPoints(keyPoints); | ||
} | ||
|
||
const nextDataPoints = [simplifiedNextKeyPoints[0], ...midDataPoints, simplifiedNextKeyPoints[simplifiedNextKeyPoints.length - 1]]; | ||
const mirrorDataPoints = getMirrorDataPoints(board, nextDataPoints, simplifiedNextKeyPoints, params); | ||
// console.log(mirrorDataPoints, 'mirrorDataPoints'); | ||
|
@@ -95,14 +96,31 @@ export const getSourceAndTargetRectangle = (board: PlaitBoard, element: PlaitLin | |
const target = handleRefPair.target; | ||
targetElement = createFakeElement(target.point, target.vector); | ||
} | ||
const sourceRectangle = RectangleClient.inflate( | ||
RectangleClient.getRectangleByPoints(sourceElement.points), | ||
getStrokeWidthByElement(sourceElement) * 2 | ||
|
||
let sourceRectangle = RectangleClient.getRectangleByPoints(sourceElement.points); | ||
MissLixf marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const sourceShape = getShape(sourceElement); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sourceShape 和 sourceEngine 有用到吗? |
||
const sourceEngine = getEngine(sourceShape); | ||
const sourceElementCornerPoints = sourceEngine.getCornerPoints(sourceRectangle); | ||
const rotatedSourceElementCornerPoints = rotatePoints( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 判断 hasValidAngle |
||
sourceElementCornerPoints, | ||
RectangleClient.getCenterPoint(sourceRectangle), | ||
sourceElement.angle | ||
); | ||
const targetRectangle = RectangleClient.inflate( | ||
RectangleClient.getRectangleByPoints(targetElement.points), | ||
getStrokeWidthByElement(targetElement) * 2 | ||
sourceRectangle = RectangleClient.getRectangleByPoints(rotatedSourceElementCornerPoints); | ||
sourceRectangle = RectangleClient.inflate(sourceRectangle, getStrokeWidthByElement(sourceElement) * 2); | ||
|
||
let targetRectangle = RectangleClient.getRectangleByPoints(targetElement.points); | ||
const shape = getShape(targetElement); | ||
const engine = getEngine(shape); | ||
const targetElementCornerPoints = engine.getCornerPoints(targetRectangle); | ||
const rotatedTargetElementCornerPoints = rotatePoints( | ||
targetElementCornerPoints, | ||
RectangleClient.getCenterPoint(targetRectangle), | ||
targetElement.angle | ||
); | ||
targetRectangle = RectangleClient.getRectangleByPoints(rotatedTargetElementCornerPoints); | ||
targetRectangle = RectangleClient.inflate(targetRectangle, getStrokeWidthByElement(targetElement) * 2); | ||
|
||
return { | ||
sourceRectangle, | ||
targetRectangle | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
验证 hasValidAngle