Add custom anchors for transformer
This commit is contained in:
parent
0b2f9593c2
commit
98d9b526c8
@ -1,6 +1,6 @@
|
|||||||
import Konva from "konva";
|
import Konva from "konva";
|
||||||
import { Transform } from "konva/lib/Util";
|
import { Transform } from "konva/lib/Util";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useMemo, useRef } from "react";
|
||||||
import { Transformer as KonvaTransformer } from "react-konva";
|
import { Transformer as KonvaTransformer } from "react-konva";
|
||||||
|
|
||||||
import { useGridCellPixelSize } from "../../contexts/GridContext";
|
import { useGridCellPixelSize } from "../../contexts/GridContext";
|
||||||
@ -8,6 +8,9 @@ import { useSetPreventMapInteraction } from "../../contexts/MapInteractionContex
|
|||||||
import { roundTo } from "../../helpers/shared";
|
import { roundTo } from "../../helpers/shared";
|
||||||
import Vector2 from "../../helpers/Vector2";
|
import Vector2 from "../../helpers/Vector2";
|
||||||
|
|
||||||
|
import scaleDark from "../../images/ScaleDark.png";
|
||||||
|
import rotateDark from "../../images/RotateDark.png";
|
||||||
|
|
||||||
type ResizerProps = {
|
type ResizerProps = {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
nodeRef: React.RefObject<Konva.Node>;
|
nodeRef: React.RefObject<Konva.Node>;
|
||||||
@ -25,14 +28,42 @@ function Transformer({
|
|||||||
|
|
||||||
const gridCellPixelSize = useGridCellPixelSize();
|
const gridCellPixelSize = useGridCellPixelSize();
|
||||||
|
|
||||||
|
const anchorScale = useMemo(() => getAnchorImage(192, scaleDark), []);
|
||||||
|
const anchorRotate = useMemo(() => getAnchorImage(192, rotateDark), []);
|
||||||
|
|
||||||
const transformerRef = useRef<Konva.Transformer>(null);
|
const transformerRef = useRef<Konva.Transformer>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (active && transformerRef.current && nodeRef.current) {
|
if (active && transformerRef.current && nodeRef.current) {
|
||||||
// we need to attach transformer manually
|
// we need to attach transformer manually
|
||||||
transformerRef.current.nodes([nodeRef.current]);
|
transformerRef.current.nodes([nodeRef.current]);
|
||||||
|
|
||||||
|
const middleLeft =
|
||||||
|
transformerRef.current.findOne<Konva.Rect>(".middle-left");
|
||||||
|
const middleRight =
|
||||||
|
transformerRef.current.findOne<Konva.Rect>(".middle-right");
|
||||||
|
const rotater = transformerRef.current.findOne<Konva.Rect>(".rotater");
|
||||||
|
|
||||||
|
middleLeft.fillPriority("pattern");
|
||||||
|
middleLeft.fillPatternImage(anchorScale);
|
||||||
|
middleLeft.strokeEnabled(false);
|
||||||
|
middleLeft.fillPatternScaleX(-0.25);
|
||||||
|
middleLeft.fillPatternScaleY(0.25);
|
||||||
|
|
||||||
|
middleRight.fillPriority("pattern");
|
||||||
|
middleRight.fillPatternImage(anchorScale);
|
||||||
|
middleRight.strokeEnabled(false);
|
||||||
|
middleRight.fillPatternScaleX(0.25);
|
||||||
|
middleRight.fillPatternScaleY(0.25);
|
||||||
|
|
||||||
|
rotater.fillPriority("pattern");
|
||||||
|
rotater.fillPatternImage(anchorRotate);
|
||||||
|
rotater.strokeEnabled(false);
|
||||||
|
rotater.fillPatternScaleX(0.25);
|
||||||
|
rotater.fillPatternScaleY(0.25);
|
||||||
|
|
||||||
transformerRef.current.getLayer()?.batchDraw();
|
transformerRef.current.getLayer()?.batchDraw();
|
||||||
}
|
}
|
||||||
}, [active, nodeRef]);
|
}, [active, nodeRef, anchorScale]);
|
||||||
|
|
||||||
const movingAnchorRef = useRef<string>();
|
const movingAnchorRef = useRef<string>();
|
||||||
function handleTransformStart(e: Konva.KonvaEventObject<Event>) {
|
function handleTransformStart(e: Konva.KonvaEventObject<Event>) {
|
||||||
@ -132,19 +163,38 @@ function Transformer({
|
|||||||
centeredScaling={true}
|
centeredScaling={true}
|
||||||
rotationSnaps={[...Array(24).keys()].map((n) => n * 15)}
|
rotationSnaps={[...Array(24).keys()].map((n) => n * 15)}
|
||||||
rotateAnchorOffset={20}
|
rotateAnchorOffset={20}
|
||||||
anchorCornerRadius={10}
|
|
||||||
enabledAnchors={["middle-left", "middle-right"]}
|
enabledAnchors={["middle-left", "middle-right"]}
|
||||||
flipEnabled={false}
|
flipEnabled={false}
|
||||||
ignoreStroke={true}
|
ignoreStroke={true}
|
||||||
borderStroke="transparent"
|
borderStroke="invisible"
|
||||||
anchorStroke="hsl(210, 50%, 96%"
|
anchorStroke="invisible"
|
||||||
anchorFill="hsla(230, 25%, 15%, 80%)"
|
anchorCornerRadius={24}
|
||||||
anchorStrokeWidth={3}
|
borderStrokeWidth={0}
|
||||||
borderStrokeWidth={2}
|
anchorSize={48}
|
||||||
anchorSize={15}
|
|
||||||
useSingleNodeRotation={true}
|
useSingleNodeRotation={true}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAnchorImage(size: number, source: string) {
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
canvas.width = size;
|
||||||
|
canvas.height = size;
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
const image = new Image();
|
||||||
|
image.src = source;
|
||||||
|
image.onload = () => {
|
||||||
|
const imageRatio = image.width / image.height;
|
||||||
|
const imageWidth = canvas.height * imageRatio;
|
||||||
|
ctx?.drawImage(
|
||||||
|
image,
|
||||||
|
canvas.width / 2 - imageWidth / 2,
|
||||||
|
0,
|
||||||
|
imageWidth,
|
||||||
|
canvas.height
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
|
||||||
export default Transformer;
|
export default Transformer;
|
||||||
|
BIN
src/images/RotateDark.png
Normal file
BIN
src/images/RotateDark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
BIN
src/images/ScaleDark.png
Normal file
BIN
src/images/ScaleDark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
Loading…
Reference in New Issue
Block a user