Added fog polygon tool and changed fog interaction method
This commit is contained in:
parent
5a93d9a526
commit
aa4ba33a0b
@ -48,7 +48,7 @@ function Map({
|
|||||||
|
|
||||||
const [selectedToolId, setSelectedToolId] = useState("pan");
|
const [selectedToolId, setSelectedToolId] = useState("pan");
|
||||||
const [toolSettings, setToolSettings] = useState({
|
const [toolSettings, setToolSettings] = useState({
|
||||||
fog: { type: "add", useEdgeSnapping: true, useGridSnapping: false },
|
fog: { type: "polygon", useEdgeSnapping: false, useFogCut: false },
|
||||||
brush: {
|
brush: {
|
||||||
color: "darkGray",
|
color: "darkGray",
|
||||||
type: "stroke",
|
type: "stroke",
|
||||||
|
@ -159,6 +159,7 @@ function MapDrawing({
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Move away from this as it is too slow to respond
|
||||||
useMapBrush(isEditing, handleShapeDraw);
|
useMapBrush(isEditing, handleShapeDraw);
|
||||||
|
|
||||||
function handleShapeOver(shape, isDown) {
|
function handleShapeOver(shape, isDown) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useContext, useState, useCallback } from "react";
|
import React, { useContext, useState, useEffect } from "react";
|
||||||
import shortid from "shortid";
|
import shortid from "shortid";
|
||||||
import { Group } from "react-konva";
|
import { Group } from "react-konva";
|
||||||
import useImage from "use-image";
|
import useImage from "use-image";
|
||||||
@ -6,6 +6,7 @@ import useImage from "use-image";
|
|||||||
import diagonalPattern from "../../images/DiagonalPattern.png";
|
import diagonalPattern from "../../images/DiagonalPattern.png";
|
||||||
|
|
||||||
import MapInteractionContext from "../../contexts/MapInteractionContext";
|
import MapInteractionContext from "../../contexts/MapInteractionContext";
|
||||||
|
import MapStageContext from "../../contexts/MapStageContext";
|
||||||
|
|
||||||
import { compare as comparePoints } from "../../helpers/vector2";
|
import { compare as comparePoints } from "../../helpers/vector2";
|
||||||
import {
|
import {
|
||||||
@ -14,8 +15,10 @@ import {
|
|||||||
getStrokeWidth,
|
getStrokeWidth,
|
||||||
} from "../../helpers/drawing";
|
} from "../../helpers/drawing";
|
||||||
import colors from "../../helpers/colors";
|
import colors from "../../helpers/colors";
|
||||||
import useMapBrush from "../../helpers/useMapBrush";
|
import {
|
||||||
import { HoleyLine } from "../../helpers/konva";
|
HoleyLine,
|
||||||
|
getRelativePointerPositionNormalized,
|
||||||
|
} from "../../helpers/konva";
|
||||||
|
|
||||||
function MapFog({
|
function MapFog({
|
||||||
shapes,
|
shapes,
|
||||||
@ -28,6 +31,7 @@ function MapFog({
|
|||||||
gridSize,
|
gridSize,
|
||||||
}) {
|
}) {
|
||||||
const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext);
|
const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext);
|
||||||
|
const mapStageRef = useContext(MapStageContext);
|
||||||
const [drawingShape, setDrawingShape] = useState(null);
|
const [drawingShape, setDrawingShape] = useState(null);
|
||||||
const [isBrushDown, setIsBrushDown] = useState(false);
|
const [isBrushDown, setIsBrushDown] = useState(false);
|
||||||
const [editingShapes, setEditingShapes] = useState([]);
|
const [editingShapes, setEditingShapes] = useState([]);
|
||||||
@ -40,39 +44,35 @@ function MapFog({
|
|||||||
|
|
||||||
const [patternImage] = useImage(diagonalPattern);
|
const [patternImage] = useImage(diagonalPattern);
|
||||||
|
|
||||||
const handleBrushUp = useCallback(() => {
|
useEffect(() => {
|
||||||
setIsBrushDown(false);
|
if (!isEditing) {
|
||||||
if (editingShapes.length > 0) {
|
return;
|
||||||
if (selectedToolSettings.type === "remove") {
|
|
||||||
onShapesRemove(editingShapes.map((shape) => shape.id));
|
|
||||||
} else if (selectedToolSettings.type === "toggle") {
|
|
||||||
onShapesEdit(
|
|
||||||
editingShapes.map((shape) => ({ ...shape, visible: !shape.visible }))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
setEditingShapes([]);
|
|
||||||
}
|
|
||||||
}, [editingShapes, onShapesRemove, onShapesEdit, selectedToolSettings]);
|
|
||||||
|
|
||||||
const handleShapeDraw = useCallback(
|
const mapStage = mapStageRef.current;
|
||||||
(brushState, mapBrushPosition) => {
|
|
||||||
function startShape() {
|
function getBrushPosition() {
|
||||||
const brushPosition = getBrushPositionForTool(
|
const mapImage = mapStage.findOne("#mapImage");
|
||||||
mapBrushPosition,
|
return getBrushPositionForTool(
|
||||||
|
getRelativePointerPositionNormalized(mapImage),
|
||||||
selectedToolId,
|
selectedToolId,
|
||||||
selectedToolSettings,
|
selectedToolSettings,
|
||||||
gridSize,
|
gridSize,
|
||||||
shapes
|
shapes
|
||||||
);
|
);
|
||||||
if (
|
}
|
||||||
selectedToolSettings.type === "add" ||
|
|
||||||
selectedToolSettings.type === "subtract"
|
function handleBrushDown() {
|
||||||
) {
|
const brushPosition = getBrushPosition();
|
||||||
|
if (selectedToolSettings.type === "brush") {
|
||||||
setDrawingShape({
|
setDrawingShape({
|
||||||
type: "fog",
|
type: "fog",
|
||||||
data: { points: [brushPosition], holes: [] },
|
data: {
|
||||||
|
points: [brushPosition],
|
||||||
|
holes: [],
|
||||||
|
},
|
||||||
strokeWidth: 0.5,
|
strokeWidth: 0.5,
|
||||||
color: selectedToolSettings.type === "add" ? "black" : "red",
|
color: selectedToolSettings.useFogSubtract ? "red" : "black",
|
||||||
blend: false,
|
blend: false,
|
||||||
id: shortid.generate(),
|
id: shortid.generate(),
|
||||||
visible: true,
|
visible: true,
|
||||||
@ -81,18 +81,13 @@ function MapFog({
|
|||||||
setIsBrushDown(true);
|
setIsBrushDown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function continueShape() {
|
function handleBrushMove() {
|
||||||
const brushPosition = getBrushPositionForTool(
|
|
||||||
mapBrushPosition,
|
|
||||||
selectedToolId,
|
|
||||||
selectedToolSettings,
|
|
||||||
gridSize,
|
|
||||||
shapes
|
|
||||||
);
|
|
||||||
if (
|
if (
|
||||||
selectedToolSettings.type === "add" ||
|
selectedToolSettings.type === "brush" &&
|
||||||
selectedToolSettings.type === "subtract"
|
isBrushDown &&
|
||||||
|
drawingShape
|
||||||
) {
|
) {
|
||||||
|
const brushPosition = getBrushPosition();
|
||||||
setDrawingShape((prevShape) => {
|
setDrawingShape((prevShape) => {
|
||||||
const prevPoints = prevShape.data.points;
|
const prevPoints = prevShape.data.points;
|
||||||
if (
|
if (
|
||||||
@ -113,13 +108,33 @@ function MapFog({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (selectedToolSettings.type === "polygon" && drawingShape) {
|
||||||
|
const brushPosition = getBrushPosition();
|
||||||
|
setDrawingShape((prevShape) => {
|
||||||
|
return {
|
||||||
|
...prevShape,
|
||||||
|
data: {
|
||||||
|
...prevShape.data,
|
||||||
|
points: [...prevShape.data.points.slice(0, -1), brushPosition],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function endShape() {
|
function handleBrushUp() {
|
||||||
if (selectedToolSettings.type === "add" && drawingShape) {
|
if (selectedToolSettings.type === "brush" && drawingShape) {
|
||||||
|
const subtract = selectedToolSettings.useFogSubtract;
|
||||||
|
|
||||||
if (drawingShape.data.points.length > 1) {
|
if (drawingShape.data.points.length > 1) {
|
||||||
|
let shapeData = {};
|
||||||
|
if (subtract) {
|
||||||
|
shapeData = { id: drawingShape.id, type: drawingShape.type };
|
||||||
|
} else {
|
||||||
|
shapeData = drawingShape;
|
||||||
|
}
|
||||||
const shape = {
|
const shape = {
|
||||||
...drawingShape,
|
...shapeData,
|
||||||
data: {
|
data: {
|
||||||
...drawingShape.data,
|
...drawingShape.data,
|
||||||
points: simplifyPoints(
|
points: simplifyPoints(
|
||||||
@ -130,59 +145,108 @@ function MapFog({
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
if (subtract) {
|
||||||
|
onShapeSubtract(shape);
|
||||||
|
} else {
|
||||||
onShapeAdd(shape);
|
onShapeAdd(shape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (selectedToolSettings.type === "subtract" && drawingShape) {
|
|
||||||
if (drawingShape.data.points.length > 1) {
|
setDrawingShape(null);
|
||||||
const shape = {
|
}
|
||||||
|
|
||||||
|
if (selectedToolSettings.type === "polygon") {
|
||||||
|
const brushPosition = getBrushPosition();
|
||||||
|
setDrawingShape({
|
||||||
|
type: "fog",
|
||||||
data: {
|
data: {
|
||||||
...drawingShape.data,
|
points: [
|
||||||
points: simplifyPoints(
|
...(drawingShape ? drawingShape.data.points : [brushPosition]),
|
||||||
drawingShape.data.points,
|
brushPosition,
|
||||||
gridSize,
|
],
|
||||||
// Downscale fog as smoothing doesn't currently work with edge snapping
|
holes: [],
|
||||||
stageScale / 2
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
|
strokeWidth: 0.5,
|
||||||
|
color: selectedToolSettings.useFogSubtract ? "red" : "black",
|
||||||
|
blend: false,
|
||||||
|
id: shortid.generate(),
|
||||||
|
visible: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editingShapes.length > 0) {
|
||||||
|
if (selectedToolSettings.type === "remove") {
|
||||||
|
onShapesRemove(editingShapes.map((shape) => shape.id));
|
||||||
|
} else if (selectedToolSettings.type === "toggle") {
|
||||||
|
onShapesEdit(
|
||||||
|
editingShapes.map((shape) => ({
|
||||||
|
...shape,
|
||||||
|
visible: !shape.visible,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
setEditingShapes([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsBrushDown(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKeyDown(event) {
|
||||||
|
if (
|
||||||
|
event.key === "Enter" &&
|
||||||
|
selectedToolSettings.type === "polygon" &&
|
||||||
|
drawingShape
|
||||||
|
) {
|
||||||
|
const subtract = selectedToolSettings.useFogSubtract;
|
||||||
|
const data = {
|
||||||
|
...drawingShape.data,
|
||||||
|
// Remove the last point as it hasn't been placed yet
|
||||||
|
points: drawingShape.data.points.slice(0, -1),
|
||||||
|
};
|
||||||
|
if (subtract) {
|
||||||
|
onShapeSubtract({
|
||||||
id: drawingShape.id,
|
id: drawingShape.id,
|
||||||
type: drawingShape.type,
|
type: drawingShape.type,
|
||||||
};
|
data: data,
|
||||||
onShapeSubtract(shape);
|
});
|
||||||
}
|
} else {
|
||||||
}
|
onShapeAdd({ ...drawingShape, data: data });
|
||||||
setDrawingShape(null);
|
|
||||||
handleBrushUp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (brushState) {
|
setDrawingShape(null);
|
||||||
case "first":
|
|
||||||
startShape();
|
|
||||||
return;
|
|
||||||
case "drawing":
|
|
||||||
continueShape();
|
|
||||||
return;
|
|
||||||
case "last":
|
|
||||||
endShape();
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
},
|
if (event.key === "Escape" && drawingShape) {
|
||||||
[
|
setDrawingShape(null);
|
||||||
selectedToolId,
|
}
|
||||||
selectedToolSettings,
|
}
|
||||||
|
|
||||||
|
mapStage.on("mousedown", handleBrushDown);
|
||||||
|
mapStage.on("mousemove", handleBrushMove);
|
||||||
|
mapStage.on("mouseup", handleBrushUp);
|
||||||
|
mapStage.container().addEventListener("keydown", handleKeyDown);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
mapStage.off("mousedown", handleBrushDown);
|
||||||
|
mapStage.off("mousemove", handleBrushMove);
|
||||||
|
mapStage.off("mouseup", handleBrushUp);
|
||||||
|
mapStage.container().removeEventListener("keydown", handleKeyDown);
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
mapStageRef,
|
||||||
|
isEditing,
|
||||||
|
drawingShape,
|
||||||
|
editingShapes,
|
||||||
gridSize,
|
gridSize,
|
||||||
stageScale,
|
isBrushDown,
|
||||||
onShapeAdd,
|
onShapeAdd,
|
||||||
onShapeSubtract,
|
onShapeSubtract,
|
||||||
|
onShapesEdit,
|
||||||
|
onShapesRemove,
|
||||||
|
selectedToolId,
|
||||||
|
selectedToolSettings,
|
||||||
shapes,
|
shapes,
|
||||||
drawingShape,
|
stageScale,
|
||||||
handleBrushUp,
|
]);
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
useMapBrush(isEditing, handleShapeDraw);
|
|
||||||
|
|
||||||
function handleShapeOver(shape, isDown) {
|
function handleShapeOver(shape, isDown) {
|
||||||
if (shouldHover && isDown) {
|
if (shouldHover && isDown) {
|
||||||
|
@ -11,7 +11,9 @@ import useDataSource from "../../helpers/useDataSource";
|
|||||||
import { mapSources as defaultMapSources } from "../../maps";
|
import { mapSources as defaultMapSources } from "../../maps";
|
||||||
|
|
||||||
import { MapInteractionProvider } from "../../contexts/MapInteractionContext";
|
import { MapInteractionProvider } from "../../contexts/MapInteractionContext";
|
||||||
import MapStageContext from "../../contexts/MapStageContext";
|
import MapStageContext, {
|
||||||
|
MapStageProvider,
|
||||||
|
} from "../../contexts/MapStageContext";
|
||||||
import AuthContext from "../../contexts/AuthContext";
|
import AuthContext from "../../contexts/AuthContext";
|
||||||
|
|
||||||
const wheelZoomSpeed = -0.001;
|
const wheelZoomSpeed = -0.001;
|
||||||
@ -201,6 +203,14 @@ function MapInteraction({ map, children, controls, selectedToolId }) {
|
|||||||
mapDragPositionRef,
|
mapDragPositionRef,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enable keyboard interaction for map stage container
|
||||||
|
useEffect(() => {
|
||||||
|
const container = mapStageRef.current.container();
|
||||||
|
container.tabIndex = 1;
|
||||||
|
container.style.outline = "none";
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -234,7 +244,9 @@ function MapInteraction({ map, children, controls, selectedToolId }) {
|
|||||||
{/* Forward auth context to konva elements */}
|
{/* Forward auth context to konva elements */}
|
||||||
<AuthContext.Provider value={auth}>
|
<AuthContext.Provider value={auth}>
|
||||||
<MapInteractionProvider value={mapInteraction}>
|
<MapInteractionProvider value={mapInteraction}>
|
||||||
|
<MapStageProvider value={mapStageRef}>
|
||||||
{children}
|
{children}
|
||||||
|
</MapStageProvider>
|
||||||
</MapInteractionProvider>
|
</MapInteractionProvider>
|
||||||
</AuthContext.Provider>
|
</AuthContext.Provider>
|
||||||
</Layer>
|
</Layer>
|
||||||
|
19
src/components/map/controls/FogSubtractToggle.js
Normal file
19
src/components/map/controls/FogSubtractToggle.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { IconButton } from "theme-ui";
|
||||||
|
|
||||||
|
import FogAddIcon from "../../../icons/FogAddIcon";
|
||||||
|
import FogSubtractIcon from "../../../icons/FogSubtractIcon";
|
||||||
|
|
||||||
|
function FogSubtractToggle({ useFogSubtract, onFogSubtractChange }) {
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
aria-label={useFogSubtract ? "Add Fog" : "Subtract Fog"}
|
||||||
|
title={useFogSubtract ? "Add Fog" : "Subtract Fog"}
|
||||||
|
onClick={() => onFogSubtractChange(!useFogSubtract)}
|
||||||
|
>
|
||||||
|
{useFogSubtract ? <FogSubtractIcon /> : <FogAddIcon />}
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FogSubtractToggle;
|
@ -3,10 +3,10 @@ import { Flex } from "theme-ui";
|
|||||||
|
|
||||||
import EdgeSnappingToggle from "./EdgeSnappingToggle";
|
import EdgeSnappingToggle from "./EdgeSnappingToggle";
|
||||||
import RadioIconButton from "./RadioIconButton";
|
import RadioIconButton from "./RadioIconButton";
|
||||||
import GridSnappingToggle from "./GridSnappingToggle";
|
import FogSubtractToggle from "./FogSubtractToggle";
|
||||||
|
|
||||||
import FogAddIcon from "../../../icons/FogAddIcon";
|
import FogBrushIcon from "../../../icons/FogBrushIcon";
|
||||||
import FogSubtractIcon from "../../../icons/FogSubtractIcon";
|
import FogPolygonIcon from "../../../icons/FogPolygonIcon";
|
||||||
import FogRemoveIcon from "../../../icons/FogRemoveIcon";
|
import FogRemoveIcon from "../../../icons/FogRemoveIcon";
|
||||||
import FogToggleIcon from "../../../icons/FogToggleIcon";
|
import FogToggleIcon from "../../../icons/FogToggleIcon";
|
||||||
|
|
||||||
@ -24,18 +24,40 @@ function BrushToolSettings({
|
|||||||
return (
|
return (
|
||||||
<Flex sx={{ alignItems: "center" }}>
|
<Flex sx={{ alignItems: "center" }}>
|
||||||
<RadioIconButton
|
<RadioIconButton
|
||||||
title="Add Fog"
|
title="Fog Polygon"
|
||||||
onClick={() => onSettingChange({ type: "add" })}
|
onClick={() => onSettingChange({ type: "polygon" })}
|
||||||
isSelected={settings.type === "add"}
|
isSelected={settings.type === "polygon"}
|
||||||
>
|
>
|
||||||
<FogAddIcon />
|
<FogPolygonIcon />
|
||||||
</RadioIconButton>
|
</RadioIconButton>
|
||||||
<RadioIconButton
|
<RadioIconButton
|
||||||
title="Subtract Fog"
|
title="Fog Brush"
|
||||||
onClick={() => onSettingChange({ type: "subtract" })}
|
onClick={() => onSettingChange({ type: "brush" })}
|
||||||
isSelected={settings.type === "subtract"}
|
isSelected={settings.type === "brush"}
|
||||||
>
|
>
|
||||||
<FogSubtractIcon />
|
<FogBrushIcon />
|
||||||
|
</RadioIconButton>
|
||||||
|
<Divider vertical />
|
||||||
|
<FogSubtractToggle
|
||||||
|
useFogSubtract={settings.useFogSubtract}
|
||||||
|
onFogSubtractChange={(useFogSubtract) =>
|
||||||
|
onSettingChange({ useFogSubtract })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{/* TODO: Re-enable edge snapping when holes are fixed */}
|
||||||
|
{/* <EdgeSnappingToggle
|
||||||
|
useEdgeSnapping={settings.useEdgeSnapping}
|
||||||
|
onEdgeSnappingChange={(useEdgeSnapping) =>
|
||||||
|
onSettingChange({ useEdgeSnapping })
|
||||||
|
}
|
||||||
|
/> */}
|
||||||
|
<Divider vertical />
|
||||||
|
<RadioIconButton
|
||||||
|
title="Toggle Fog"
|
||||||
|
onClick={() => onSettingChange({ type: "toggle" })}
|
||||||
|
isSelected={settings.type === "toggle"}
|
||||||
|
>
|
||||||
|
<FogToggleIcon />
|
||||||
</RadioIconButton>
|
</RadioIconButton>
|
||||||
<RadioIconButton
|
<RadioIconButton
|
||||||
title="Remove Fog"
|
title="Remove Fog"
|
||||||
@ -44,26 +66,6 @@ function BrushToolSettings({
|
|||||||
>
|
>
|
||||||
<FogRemoveIcon />
|
<FogRemoveIcon />
|
||||||
</RadioIconButton>
|
</RadioIconButton>
|
||||||
<RadioIconButton
|
|
||||||
title="Toggle Fog"
|
|
||||||
onClick={() => onSettingChange({ type: "toggle" })}
|
|
||||||
isSelected={settings.type === "toggle"}
|
|
||||||
>
|
|
||||||
<FogToggleIcon />
|
|
||||||
</RadioIconButton>
|
|
||||||
<Divider vertical />
|
|
||||||
<EdgeSnappingToggle
|
|
||||||
useEdgeSnapping={settings.useEdgeSnapping}
|
|
||||||
onEdgeSnappingChange={(useEdgeSnapping) =>
|
|
||||||
onSettingChange({ useEdgeSnapping })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<GridSnappingToggle
|
|
||||||
useGridSnapping={settings.useGridSnapping}
|
|
||||||
onGridSnappingChange={(useGridSnapping) =>
|
|
||||||
onSettingChange({ useGridSnapping })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Divider vertical />
|
<Divider vertical />
|
||||||
<UndoButton
|
<UndoButton
|
||||||
onClick={() => onToolAction("fogUndo")}
|
onClick={() => onToolAction("fogUndo")}
|
||||||
|
@ -105,3 +105,18 @@ export function HoleyLine({ holes, ...props }) {
|
|||||||
|
|
||||||
return <Line sceneFunc={sceneFunc} {...props} />;
|
return <Line sceneFunc={sceneFunc} {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRelativePointerPosition(node) {
|
||||||
|
let transform = node.getAbsoluteTransform().copy();
|
||||||
|
transform.invert();
|
||||||
|
let posision = node.getStage().getPointerPosition();
|
||||||
|
return transform.point(posision);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRelativePointerPositionNormalized(node) {
|
||||||
|
const relativePosition = getRelativePointerPosition(node);
|
||||||
|
return {
|
||||||
|
x: relativePosition.x / node.width(),
|
||||||
|
y: relativePosition.y / node.height(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -7,15 +7,10 @@ function EraseToolIcon() {
|
|||||||
height="24"
|
height="24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
>
|
|
||||||
<g fill="none" fillRule="evenodd">
|
|
||||||
<path d="M0 0h24v24H0z" />
|
|
||||||
<path
|
|
||||||
d="M3.212 12.303c-1 1-1.182 2.455-.404 3.233l5.656 5.656c.778.778 2.233.596 3.233-.404l9.091-9.091c1-1 1.182-2.455.404-3.233l-5.656-5.656c-.778-.778-2.233-.596-3.233.404l-9.091 9.091zm6.667-2.424l4.242 4.242c.39.39.485.93.212 1.202l-3.96 3.96c-.272.272-.813.177-1.201-.212l-4.243-4.243c-.389-.388-.484-.93-.212-1.202l3.96-3.96c.272-.272.813-.176 1.202.213z"
|
|
||||||
fill="currentcolor"
|
fill="currentcolor"
|
||||||
fillRule="nonzero"
|
>
|
||||||
/>
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
</g>
|
<path d="M3.212 12.303c-1 1-1.182 2.455-.404 3.233l5.656 5.656c.778.778 2.233.596 3.233-.404l9.091-9.091c1-1 1.182-2.455.404-3.233l-5.656-5.656c-.778-.778-2.233-.596-3.233.404l-9.091 9.091zm6.667-2.424l4.242 4.242c.39.39.485.93.212 1.202l-3.96 3.96c-.272.272-.813.177-1.201-.212l-4.243-4.243c-.389-.388-.484-.93-.212-1.202l3.96-3.96c.272-.272.813-.176 1.202.213z" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
18
src/icons/FogBrushIcon.js
Normal file
18
src/icons/FogBrushIcon.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
function FogBrushIcon() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
fill="currentcolor"
|
||||||
|
>
|
||||||
|
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||||
|
<path d="M18 4V3c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6h1v4h-9c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-9h7c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1h-2z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FogBrushIcon;
|
18
src/icons/FogPolygonIcon.js
Normal file
18
src/icons/FogPolygonIcon.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
function FogPolygonIcon() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
fill="currentcolor"
|
||||||
|
>
|
||||||
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M15.858 20a1 1 0 110 2h-8a1 1 0 010-2h8zm-5-17.998v9.516a2 2 0 102 0V2.12l5.725 10.312a1 1 0 01.049.87l-.058.117-3.093 5.333a1 1 0 01-.865.498H8.941a1 1 0 01-.875-.516L5.125 13.41a1 1 0 01-.002-.965l5.735-10.443z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FogPolygonIcon;
|
@ -10,7 +10,7 @@ function FogRemoveIcon() {
|
|||||||
fill="currentcolor"
|
fill="currentcolor"
|
||||||
>
|
>
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M19.35 10.04A7.49 7.49 0 0012 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 000 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zm-3.814.839L13.414 13l2.122 2.121a1.003 1.003 0 010 1.415 1.003 1.003 0 01-1.415 0L12 14.414l-2.121 2.122a1.003 1.003 0 01-1.415 0 1.003 1.003 0 010-1.415L10.586 13l-2.122-2.121a1.003 1.003 0 010-1.415 1.003 1.003 0 011.415 0L12 11.586l2.121-2.122a1.003 1.003 0 011.415 0 1.003 1.003 0 010 1.415z" />
|
<path d="M3.212 12.303c-1 1-1.182 2.455-.404 3.233l5.656 5.656c.778.778 2.233.596 3.233-.404l9.091-9.091c1-1 1.182-2.455.404-3.233l-5.656-5.656c-.778-.778-2.233-.596-3.233.404l-9.091 9.091zm6.667-2.424l4.242 4.242c.39.39.485.93.212 1.202l-3.96 3.96c-.272.272-.813.177-1.201-.212l-4.243-4.243c-.389-.388-.484-.93-.212-1.202l3.96-3.96c.272-.272.813-.176 1.202.213z" />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user