mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: Elbow arrow segment fixing & positioning (#8952)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com> Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
parent
8551823da9
commit
91ebf8b0ea
33 changed files with 3282 additions and 1716 deletions
|
@ -29,7 +29,7 @@ import {
|
|||
getOmitSidesForDevice,
|
||||
shouldShowBoundingBox,
|
||||
} from "../element/transformHandles";
|
||||
import { arrayToMap, throttleRAF } from "../utils";
|
||||
import { arrayToMap, invariant, throttleRAF } from "../utils";
|
||||
import {
|
||||
DEFAULT_TRANSFORM_HANDLE_SPACING,
|
||||
FRAME_STYLE,
|
||||
|
@ -78,9 +78,32 @@ import type {
|
|||
InteractiveSceneRenderConfig,
|
||||
RenderableElementsMap,
|
||||
} from "../scene/types";
|
||||
import type { GlobalPoint, LocalPoint, Radians } from "../../math";
|
||||
import {
|
||||
pointFrom,
|
||||
type GlobalPoint,
|
||||
type LocalPoint,
|
||||
type Radians,
|
||||
} from "../../math";
|
||||
import { getCornerRadius } from "../shapes";
|
||||
|
||||
const renderElbowArrowMidPointHighlight = (
|
||||
context: CanvasRenderingContext2D,
|
||||
appState: InteractiveCanvasAppState,
|
||||
) => {
|
||||
invariant(appState.selectedLinearElement, "selectedLinearElement is null");
|
||||
|
||||
const { segmentMidPointHoveredCoords } = appState.selectedLinearElement;
|
||||
|
||||
invariant(segmentMidPointHoveredCoords, "midPointCoords is null");
|
||||
|
||||
context.save();
|
||||
context.translate(appState.scrollX, appState.scrollY);
|
||||
|
||||
highlightPoint(segmentMidPointHoveredCoords, context, appState);
|
||||
|
||||
context.restore();
|
||||
};
|
||||
|
||||
const renderLinearElementPointHighlight = (
|
||||
context: CanvasRenderingContext2D,
|
||||
appState: InteractiveCanvasAppState,
|
||||
|
@ -490,7 +513,7 @@ const renderLinearPointHandles = (
|
|||
context.save();
|
||||
context.translate(appState.scrollX, appState.scrollY);
|
||||
context.lineWidth = 1 / appState.zoom.value;
|
||||
const points = LinearElementEditor.getPointsGlobalCoordinates(
|
||||
const points: GlobalPoint[] = LinearElementEditor.getPointsGlobalCoordinates(
|
||||
element,
|
||||
elementsMap,
|
||||
);
|
||||
|
@ -510,55 +533,57 @@ const renderLinearPointHandles = (
|
|||
renderSingleLinearPoint(context, appState, point, radius, isSelected);
|
||||
});
|
||||
|
||||
//Rendering segment mid points
|
||||
const midPoints = LinearElementEditor.getEditorMidPoints(
|
||||
element,
|
||||
elementsMap,
|
||||
appState,
|
||||
).filter((midPoint): midPoint is GlobalPoint => midPoint !== null);
|
||||
|
||||
midPoints.forEach((segmentMidPoint) => {
|
||||
if (
|
||||
appState?.selectedLinearElement?.segmentMidPointHoveredCoords &&
|
||||
LinearElementEditor.arePointsEqual(
|
||||
segmentMidPoint,
|
||||
appState.selectedLinearElement.segmentMidPointHoveredCoords,
|
||||
)
|
||||
) {
|
||||
// The order of renderingSingleLinearPoint and highLight points is different
|
||||
// inside vs outside editor as hover states are different,
|
||||
// in editor when hovered the original point is not visible as hover state fully covers it whereas outside the
|
||||
// editor original point is visible and hover state is just an outer circle.
|
||||
if (appState.editingLinearElement) {
|
||||
// Rendering segment mid points
|
||||
if (isElbowArrow(element)) {
|
||||
const fixedSegments =
|
||||
element.fixedSegments?.map((segment) => segment.index) || [];
|
||||
points.slice(0, -1).forEach((p, idx) => {
|
||||
if (
|
||||
!LinearElementEditor.isSegmentTooShort(
|
||||
element,
|
||||
points[idx + 1],
|
||||
points[idx],
|
||||
idx,
|
||||
appState.zoom,
|
||||
)
|
||||
) {
|
||||
renderSingleLinearPoint(
|
||||
context,
|
||||
appState,
|
||||
segmentMidPoint,
|
||||
radius,
|
||||
false,
|
||||
);
|
||||
highlightPoint(segmentMidPoint, context, appState);
|
||||
} else {
|
||||
highlightPoint(segmentMidPoint, context, appState);
|
||||
renderSingleLinearPoint(
|
||||
context,
|
||||
appState,
|
||||
segmentMidPoint,
|
||||
radius,
|
||||
pointFrom<GlobalPoint>(
|
||||
(p[0] + points[idx + 1][0]) / 2,
|
||||
(p[1] + points[idx + 1][1]) / 2,
|
||||
),
|
||||
POINT_HANDLE_SIZE / 2,
|
||||
false,
|
||||
!fixedSegments.includes(idx + 1),
|
||||
);
|
||||
}
|
||||
} else if (appState.editingLinearElement || points.length === 2) {
|
||||
renderSingleLinearPoint(
|
||||
context,
|
||||
appState,
|
||||
segmentMidPoint,
|
||||
POINT_HANDLE_SIZE / 2,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const midPoints = LinearElementEditor.getEditorMidPoints(
|
||||
element,
|
||||
elementsMap,
|
||||
appState,
|
||||
).filter(
|
||||
(midPoint, idx, midPoints): midPoint is GlobalPoint =>
|
||||
midPoint !== null &&
|
||||
!(isElbowArrow(element) && (idx === 0 || idx === midPoints.length - 1)),
|
||||
);
|
||||
|
||||
midPoints.forEach((segmentMidPoint) => {
|
||||
if (appState.editingLinearElement || points.length === 2) {
|
||||
renderSingleLinearPoint(
|
||||
context,
|
||||
appState,
|
||||
segmentMidPoint,
|
||||
POINT_HANDLE_SIZE / 2,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
context.restore();
|
||||
};
|
||||
|
@ -864,6 +889,12 @@ const _renderInteractiveScene = ({
|
|||
}
|
||||
|
||||
if (
|
||||
isElbowArrow(selectedElements[0]) &&
|
||||
appState.selectedLinearElement &&
|
||||
appState.selectedLinearElement.segmentMidPointHoveredCoords
|
||||
) {
|
||||
renderElbowArrowMidPointHighlight(context, appState);
|
||||
} else if (
|
||||
appState.selectedLinearElement &&
|
||||
appState.selectedLinearElement.hoverPointIndex >= 0 &&
|
||||
!(
|
||||
|
@ -875,6 +906,7 @@ const _renderInteractiveScene = ({
|
|||
) {
|
||||
renderLinearElementPointHighlight(context, appState, elementsMap);
|
||||
}
|
||||
|
||||
// Paint selected elements
|
||||
if (!appState.multiElement && !appState.editingLinearElement) {
|
||||
const showBoundingBox = shouldShowBoundingBox(selectedElements, appState);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue