Add custom anchors for transformer

This commit is contained in:
Mitchell McCaffrey 2021-08-01 21:00:48 +10:00
parent 0b2f9593c2
commit 98d9b526c8
3 changed files with 59 additions and 9 deletions

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
src/images/ScaleDark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB