From 602590dc0e289de41d486f22a21698702605d947 Mon Sep 17 00:00:00 2001 From: Axel Bocciarelli Date: Fri, 25 Aug 2023 16:42:48 +0200 Subject: [PATCH] Allow zooming on very thin selection boxes --- packages/lib/src/interactions/SelectToZoom.tsx | 2 +- packages/lib/src/interactions/hooks.ts | 6 +++++- packages/lib/src/interactions/svg/SvgRect.tsx | 15 +++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/lib/src/interactions/SelectToZoom.tsx b/packages/lib/src/interactions/SelectToZoom.tsx index bd9bdb2f4..d91d8517a 100644 --- a/packages/lib/src/interactions/SelectToZoom.tsx +++ b/packages/lib/src/interactions/SelectToZoom.tsx @@ -58,7 +58,7 @@ function SelectToZoom(props: Props) { Box.fromPoints(...html).hasMinSize(minZoom)} + validate={({ html }) => html[0].manhattanDistanceTo(html[1]) >= minZoom} onValidSelection={zoomOnSelection} {...commonProps} > diff --git a/packages/lib/src/interactions/hooks.ts b/packages/lib/src/interactions/hooks.ts index e37f4299e..8b99a53bd 100644 --- a/packages/lib/src/interactions/hooks.ts +++ b/packages/lib/src/interactions/hooks.ts @@ -52,7 +52,11 @@ export function useZoomOnSelection() { // Update camera scale first (since `moveCameraTo` relies on camera scale) const { width: zoomWidth, height: zoomHeight } = zoomBox.size; - camera.scale.set(zoomWidth / width, zoomHeight / height, 1); + camera.scale.set( + Math.max(zoomWidth, 1) / width, + Math.max(zoomHeight, 1) / height, + 1, + ); // Then move camera position moveCameraTo(zoomBox.center); diff --git a/packages/lib/src/interactions/svg/SvgRect.tsx b/packages/lib/src/interactions/svg/SvgRect.tsx index 47282a37d..4c3424950 100644 --- a/packages/lib/src/interactions/svg/SvgRect.tsx +++ b/packages/lib/src/interactions/svg/SvgRect.tsx @@ -1,8 +1,9 @@ import type { SVGProps } from 'react'; +import Box from '../box'; import type { Rect } from '../models'; -interface Props extends SVGProps { +interface Props extends SVGProps { coords: Rect; strokePosition?: 'inside' | 'outside'; // no effect without `stroke` prop; assumes `strokeWidth` of 1 unless specified explicitely as prop (CSS ignored) strokeWidth?: number; // forbid string @@ -11,22 +12,20 @@ interface Props extends SVGProps { function SvgRect(props: Props) { const { coords, strokePosition, ...svgProps } = props; - const [start, end] = coords; const { stroke, strokeWidth = 1 } = svgProps; // Shrink/grow rectangle to simulate positioning stroke inside/outside // https://stackoverflow.com/questions/7241393/can-you-control-how-an-svgs-stroke-width-is-drawn const offset = stroke && strokePosition - ? (strokeWidth / 2) * (strokePosition === 'inside' ? 1 : -1) + ? strokeWidth * (strokePosition === 'outside' ? 1 : -1) : 0; + const { min, max } = Box.fromPoints(...coords).expandBySize(offset, offset); + return ( - );