Made grid snapping have a threshold and removed the option to toggle it on and off

This commit is contained in:
Mitchell McCaffrey 2020-04-28 11:31:01 +10:00
parent 734b966a53
commit b3bf3c3598
11 changed files with 21 additions and 105 deletions

View File

@ -49,18 +49,16 @@ function Map({
const [selectedToolId, setSelectedToolId] = useState("pan"); const [selectedToolId, setSelectedToolId] = useState("pan");
const [toolSettings, setToolSettings] = useState({ const [toolSettings, setToolSettings] = useState({
fog: { type: "add", useGridSnapping: false, useEdgeSnapping: true }, fog: { type: "add", useEdgeSnapping: true },
brush: { brush: {
color: "darkGray", color: "darkGray",
type: "stroke", type: "stroke",
useBlending: false, useBlending: false,
useGridSnapping: false,
}, },
shape: { shape: {
color: "red", color: "red",
type: "rectangle", type: "rectangle",
useBlending: true, useBlending: true,
useGridSnapping: false,
}, },
}); });
function handleToolSettingChange(tool, change) { function handleToolSettingChange(tool, change) {

View File

@ -56,7 +56,7 @@ function MapDrawing({
setIsDrawing(true); setIsDrawing(true);
const brushPosition = getBrushPositionForTool( const brushPosition = getBrushPositionForTool(
position, position,
toolSettings, selectedTool,
gridSize, gridSize,
shapes shapes
); );
@ -97,7 +97,7 @@ function MapDrawing({
setPointerPosition(position); setPointerPosition(position);
const brushPosition = getBrushPositionForTool( const brushPosition = getBrushPositionForTool(
position, position,
toolSettings, selectedTool,
gridSize, gridSize,
shapes shapes
); );

View File

@ -3,7 +3,6 @@ import { Flex } from "theme-ui";
import ColorControl from "./ColorControl"; import ColorControl from "./ColorControl";
import AlphaBlendToggle from "./AlphaBlendToggle"; import AlphaBlendToggle from "./AlphaBlendToggle";
import GridSnappingToggle from "./GridSnappingToggle";
import RadioIconButton from "./RadioIconButton"; import RadioIconButton from "./RadioIconButton";
import BrushStrokeIcon from "../../../icons/BrushStrokeIcon"; import BrushStrokeIcon from "../../../icons/BrushStrokeIcon";
@ -38,12 +37,6 @@ function BrushToolSettings({ settings, onSettingChange }) {
useBlending={settings.useBlending} useBlending={settings.useBlending}
onBlendingChange={(useBlending) => onSettingChange({ useBlending })} onBlendingChange={(useBlending) => onSettingChange({ useBlending })}
/> />
<GridSnappingToggle
useGridSnapping={settings.useGridSnapping}
onGridSnappingChange={(useGridSnapping) =>
onSettingChange({ useGridSnapping })
}
/>
</Flex> </Flex>
); );
} }

View File

@ -1,7 +1,6 @@
import React from "react"; import React from "react";
import { Flex } from "theme-ui"; import { Flex } from "theme-ui";
import GridSnappingToggle from "./GridSnappingToggle";
import EdgeSnappingToggle from "./EdgeSnappingToggle"; import EdgeSnappingToggle from "./EdgeSnappingToggle";
import RadioIconButton from "./RadioIconButton"; import RadioIconButton from "./RadioIconButton";
@ -36,12 +35,6 @@ function BrushToolSettings({ settings, onSettingChange }) {
<FogToggleIcon /> <FogToggleIcon />
</RadioIconButton> </RadioIconButton>
<Divider vertical /> <Divider vertical />
<GridSnappingToggle
useGridSnapping={settings.useGridSnapping}
onGridSnappingChange={(useGridSnapping) =>
onSettingChange({ useGridSnapping })
}
/>
<EdgeSnappingToggle <EdgeSnappingToggle
useEdgeSnapping={settings.useEdgeSnapping} useEdgeSnapping={settings.useEdgeSnapping}
onEdgeSnappingChange={(useEdgeSnapping) => onEdgeSnappingChange={(useEdgeSnapping) =>

View File

@ -1,21 +0,0 @@
import React from "react";
import { IconButton } from "theme-ui";
import GridOnIcon from "../../../icons/GridOnIcon";
import GridOffIcon from "../../../icons/GridOffIcon";
function GridSnappingToggle({ useGridSnapping, onGridSnappingChange }) {
return (
<IconButton
aria-label={
useGridSnapping ? "Disable Grid Snapping" : "Enable Grid Snapping"
}
title={useGridSnapping ? "Disable Grid Snapping" : "Enable Grid Snapping"}
onClick={() => onGridSnappingChange(!useGridSnapping)}
>
{useGridSnapping ? <GridOnIcon /> : <GridOffIcon />}
</IconButton>
);
}
export default GridSnappingToggle;

View File

@ -3,7 +3,6 @@ import { Flex } from "theme-ui";
import ColorControl from "./ColorControl"; import ColorControl from "./ColorControl";
import AlphaBlendToggle from "./AlphaBlendToggle"; import AlphaBlendToggle from "./AlphaBlendToggle";
import GridSnappingToggle from "./GridSnappingToggle";
import RadioIconButton from "./RadioIconButton"; import RadioIconButton from "./RadioIconButton";
import ShapeRectangleIcon from "../../../icons/ShapeRectangleIcon"; import ShapeRectangleIcon from "../../../icons/ShapeRectangleIcon";
@ -46,12 +45,6 @@ function ShapeToolSettings({ settings, onSettingChange }) {
useBlending={settings.useBlending} useBlending={settings.useBlending}
onBlendingChange={(useBlending) => onSettingChange({ useBlending })} onBlendingChange={(useBlending) => onSettingChange({ useBlending })}
/> />
<GridSnappingToggle
useGridSnapping={settings.useGridSnapping}
onGridSnappingChange={(useGridSnapping) =>
onSettingChange({ useGridSnapping })
}
/>
</Flex> </Flex>
); );
} }

View File

@ -1,17 +1,17 @@
import { snapPositionToGrid } from "./shared";
import * as Vector2 from "./vector2"; import * as Vector2 from "./vector2";
import { toDegrees } from "./shared"; import { toDegrees } from "./shared";
import colors from "./colors"; import colors from "./colors";
export function getBrushPositionForTool( const snappingThreshold = 1 / 5;
brushPosition, export function getBrushPositionForTool(brushPosition, tool, gridSize, shapes) {
settings,
gridSize,
shapes
) {
let position = brushPosition; let position = brushPosition;
if (settings && settings.useGridSnapping) { if (tool === "shape") {
position = snapPositionToGrid(position, gridSize); const snapped = Vector2.roundTo(position, gridSize);
const minGrid = Vector2.min(gridSize);
const distance = Vector2.length(Vector2.subtract(snapped, position));
if (distance < minGrid * snappingThreshold) {
position = snapped;
}
} }
return position; return position;
@ -187,7 +187,7 @@ export function shapeToPath(shape, canvasWidth, canvasHeight) {
canvasWidth, canvasWidth,
canvasHeight canvasHeight
); );
} else if ((shape.shapeType === "rectangle", canvasWidth, canvasHeight)) { } else if (shape.shapeType === "rectangle") {
return rectangleToPath( return rectangleToPath(
data.x, data.x,
data.y, data.y,

View File

@ -28,13 +28,6 @@ export function roundTo(x, to) {
return Math.round(x / to) * to; return Math.round(x / to) * to;
} }
export function snapPositionToGrid(position, gridSize) {
return {
x: roundTo(position.x, gridSize.x),
y: roundTo(position.y, gridSize.y),
};
}
export function toRadians(angle) { export function toRadians(angle) {
return angle * (Math.PI / 180); return angle * (Math.PI / 180);
} }

View File

@ -1,4 +1,4 @@
import { toRadians } from "./shared"; import { toRadians, roundTo as roundToNumber } from "./shared";
export function lengthSquared(p) { export function lengthSquared(p) {
return p.x * p.x + p.y * p.y; return p.x * p.x + p.y * p.y;
@ -70,3 +70,10 @@ export function min(a) {
export function max(a) { export function max(a) {
return a.x > a.y ? a.x : a.y; return a.x > a.y ? a.x : a.y;
} }
export function roundTo(p, to) {
return {
x: roundToNumber(p.x, to.x),
y: roundToNumber(p.y, to.y),
};
}

View File

@ -1,20 +0,0 @@
import React from "react";
function GridOffIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 0 24 24"
width="24"
fill="currentcolor"
// Fixes bug with not firing click event when used in a button
style={{ pointerEvents: "none" }}
>
<path d="M0 0h24v24H0V0z" fill="none" />
<path d="M8 4v.89l2 2V4h4v4h-2.89l2 2H14v.89l2 2V10h4v4h-2.89l2 2H20v.89l2 2V4c0-1.1-.9-2-2-2H5.11l2 2H8zm8 0h3c.55 0 1 .45 1 1v3h-4V4zm6.16 17.88L2.12 1.84c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L2 4.55V20c0 1.1.9 2 2 2h15.45l1.3 1.3c.39.39 1.02.39 1.41 0 .39-.39.39-1.03 0-1.42zM10 12.55L11.45 14H10v-1.45zm-6-6L5.45 8H4V6.55zM8 20H5c-.55 0-1-.45-1-1v-3h4v4zm0-6H4v-4h3.45l.55.55V14zm6 6h-4v-4h3.45l.55.55V20zm2 0v-1.45L17.45 20H16z" />
</svg>
);
}
export default GridOffIcon;

View File

@ -1,20 +0,0 @@
import React from "react";
function GridOnIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 0 24 24"
width="24"
fill="currentcolor"
// Fixes bug with not firing click event when used in a button
style={{ pointerEvents: "none" }}
>
<path d="M0 0h24v24H0V0z" fill="none" />
<path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM8 20H5c-.55 0-1-.45-1-1v-3h4v4zm0-6H4v-4h4v4zm0-6H4V5c0-.55.45-1 1-1h3v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4zm5 12h-3v-4h4v3c0 .55-.45 1-1 1zm1-6h-4v-4h4v4zm0-6h-4V4h3c.55 0 1 .45 1 1v3z" />
</svg>
);
}
export default GridOnIcon;