|
@@ -44,6 +44,7 @@ import {
|
|
isBindingEnabled,
|
|
isBindingEnabled,
|
|
} from "../element/binding";
|
|
} from "../element/binding";
|
|
import {
|
|
import {
|
|
|
|
+ shouldShowBoundingBox,
|
|
TransformHandles,
|
|
TransformHandles,
|
|
TransformHandleType,
|
|
TransformHandleType,
|
|
} from "../element/transformHandles";
|
|
} from "../element/transformHandles";
|
|
@@ -61,6 +62,7 @@ import {
|
|
import { isLinearElement } from "../element/typeChecks";
|
|
import { isLinearElement } from "../element/typeChecks";
|
|
|
|
|
|
const hasEmojiSupport = supportsEmoji();
|
|
const hasEmojiSupport = supportsEmoji();
|
|
|
|
+export const DEFAULT_SPACING = 4;
|
|
|
|
|
|
const strokeRectWithRotation = (
|
|
const strokeRectWithRotation = (
|
|
context: CanvasRenderingContext2D,
|
|
context: CanvasRenderingContext2D,
|
|
@@ -219,6 +221,7 @@ const renderLinearElementPointHighlight = (
|
|
|
|
|
|
context.restore();
|
|
context.restore();
|
|
};
|
|
};
|
|
|
|
+
|
|
export const _renderScene = (
|
|
export const _renderScene = (
|
|
elements: readonly NonDeletedExcalidrawElement[],
|
|
elements: readonly NonDeletedExcalidrawElement[],
|
|
appState: AppState,
|
|
appState: AppState,
|
|
@@ -346,7 +349,6 @@ export const _renderScene = (
|
|
) {
|
|
) {
|
|
renderLinearElementPointHighlight(context, appState, renderConfig);
|
|
renderLinearElementPointHighlight(context, appState, renderConfig);
|
|
}
|
|
}
|
|
-
|
|
|
|
// Paint selected elements
|
|
// Paint selected elements
|
|
if (
|
|
if (
|
|
renderSelection &&
|
|
renderSelection &&
|
|
@@ -354,6 +356,8 @@ export const _renderScene = (
|
|
!appState.editingLinearElement
|
|
!appState.editingLinearElement
|
|
) {
|
|
) {
|
|
const locallySelectedElements = getSelectedElements(elements, appState);
|
|
const locallySelectedElements = getSelectedElements(elements, appState);
|
|
|
|
+ const showBoundingBox = shouldShowBoundingBox(locallySelectedElements);
|
|
|
|
+
|
|
const locallySelectedIds = locallySelectedElements.map(
|
|
const locallySelectedIds = locallySelectedElements.map(
|
|
(element) => element.id,
|
|
(element) => element.id,
|
|
);
|
|
);
|
|
@@ -373,9 +377,8 @@ export const _renderScene = (
|
|
renderConfig,
|
|
renderConfig,
|
|
locallySelectedElements[0] as ExcalidrawLinearElement,
|
|
locallySelectedElements[0] as ExcalidrawLinearElement,
|
|
);
|
|
);
|
|
- // render bounding box
|
|
|
|
- // (unless dragging a single linear element)
|
|
|
|
- } else if (!appState.draggingElement || !isSingleLinearElementSelected) {
|
|
|
|
|
|
+ }
|
|
|
|
+ if (showBoundingBox) {
|
|
const selections = elements.reduce((acc, element) => {
|
|
const selections = elements.reduce((acc, element) => {
|
|
const selectionColors = [];
|
|
const selectionColors = [];
|
|
// local user
|
|
// local user
|
|
@@ -434,12 +437,18 @@ export const _renderScene = (
|
|
addSelectionForGroupId(appState.editingGroupId);
|
|
addSelectionForGroupId(appState.editingGroupId);
|
|
}
|
|
}
|
|
selections.forEach((selection) =>
|
|
selections.forEach((selection) =>
|
|
- renderSelectionBorder(context, renderConfig, selection),
|
|
|
|
|
|
+ renderSelectionBorder(
|
|
|
|
+ context,
|
|
|
|
+ renderConfig,
|
|
|
|
+ selection,
|
|
|
|
+ isSingleLinearElementSelected ? DEFAULT_SPACING * 2 : DEFAULT_SPACING,
|
|
|
|
+ ),
|
|
);
|
|
);
|
|
}
|
|
}
|
|
// Paint resize transformHandles
|
|
// Paint resize transformHandles
|
|
context.save();
|
|
context.save();
|
|
context.translate(renderConfig.scrollX, renderConfig.scrollY);
|
|
context.translate(renderConfig.scrollX, renderConfig.scrollY);
|
|
|
|
+
|
|
if (locallySelectedElements.length === 1) {
|
|
if (locallySelectedElements.length === 1) {
|
|
context.fillStyle = oc.white;
|
|
context.fillStyle = oc.white;
|
|
const transformHandles = getTransformHandles(
|
|
const transformHandles = getTransformHandles(
|
|
@@ -447,10 +456,7 @@ export const _renderScene = (
|
|
renderConfig.zoom,
|
|
renderConfig.zoom,
|
|
"mouse", // when we render we don't know which pointer type so use mouse
|
|
"mouse", // when we render we don't know which pointer type so use mouse
|
|
);
|
|
);
|
|
- if (
|
|
|
|
- !appState.viewModeEnabled &&
|
|
|
|
- !isLinearElement(locallySelectedElements[0])
|
|
|
|
- ) {
|
|
|
|
|
|
+ if (!appState.viewModeEnabled && showBoundingBox) {
|
|
renderTransformHandles(
|
|
renderTransformHandles(
|
|
context,
|
|
context,
|
|
renderConfig,
|
|
renderConfig,
|
|
@@ -714,24 +720,21 @@ const renderTransformHandles = (
|
|
Object.keys(transformHandles).forEach((key) => {
|
|
Object.keys(transformHandles).forEach((key) => {
|
|
const transformHandle = transformHandles[key as TransformHandleType];
|
|
const transformHandle = transformHandles[key as TransformHandleType];
|
|
if (transformHandle !== undefined) {
|
|
if (transformHandle !== undefined) {
|
|
|
|
+ const [x, y, width, height] = transformHandle;
|
|
|
|
+
|
|
context.save();
|
|
context.save();
|
|
context.lineWidth = 1 / renderConfig.zoom.value;
|
|
context.lineWidth = 1 / renderConfig.zoom.value;
|
|
if (key === "rotation") {
|
|
if (key === "rotation") {
|
|
- fillCircle(
|
|
|
|
- context,
|
|
|
|
- transformHandle[0] + transformHandle[2] / 2,
|
|
|
|
- transformHandle[1] + transformHandle[3] / 2,
|
|
|
|
- transformHandle[2] / 2,
|
|
|
|
- );
|
|
|
|
|
|
+ fillCircle(context, x + width / 2, y + height / 2, width / 2);
|
|
} else {
|
|
} else {
|
|
strokeRectWithRotation(
|
|
strokeRectWithRotation(
|
|
context,
|
|
context,
|
|
- transformHandle[0],
|
|
|
|
- transformHandle[1],
|
|
|
|
- transformHandle[2],
|
|
|
|
- transformHandle[3],
|
|
|
|
- transformHandle[0] + transformHandle[2] / 2,
|
|
|
|
- transformHandle[1] + transformHandle[3] / 2,
|
|
|
|
|
|
+ x,
|
|
|
|
+ y,
|
|
|
|
+ width,
|
|
|
|
+ height,
|
|
|
|
+ x + width / 2,
|
|
|
|
+ y + height / 2,
|
|
angle,
|
|
angle,
|
|
true, // fill before stroke
|
|
true, // fill before stroke
|
|
);
|
|
);
|
|
@@ -752,13 +755,14 @@ const renderSelectionBorder = (
|
|
elementY2: number;
|
|
elementY2: number;
|
|
selectionColors: string[];
|
|
selectionColors: string[];
|
|
},
|
|
},
|
|
|
|
+ padding = 4,
|
|
) => {
|
|
) => {
|
|
const { angle, elementX1, elementY1, elementX2, elementY2, selectionColors } =
|
|
const { angle, elementX1, elementY1, elementX2, elementY2, selectionColors } =
|
|
elementProperties;
|
|
elementProperties;
|
|
const elementWidth = elementX2 - elementX1;
|
|
const elementWidth = elementX2 - elementX1;
|
|
const elementHeight = elementY2 - elementY1;
|
|
const elementHeight = elementY2 - elementY1;
|
|
|
|
|
|
- const dashedLinePadding = 4 / renderConfig.zoom.value;
|
|
|
|
|
|
+ const dashedLinePadding = padding / renderConfig.zoom.value;
|
|
const dashWidth = 8 / renderConfig.zoom.value;
|
|
const dashWidth = 8 / renderConfig.zoom.value;
|
|
const spaceWidth = 4 / renderConfig.zoom.value;
|
|
const spaceWidth = 4 / renderConfig.zoom.value;
|
|
|
|
|