mirror of
https://github.com/r2r90/canvas-label.git
synced 2025-12-18 05:29:26 +00:00
94 lines
2.3 KiB
TypeScript
94 lines
2.3 KiB
TypeScript
import { type ImageConfig } from "konva/lib/shapes/Image";
|
|
import { useRef, useEffect, type ElementRef } from "react";
|
|
import { Transformer, Image } from "react-konva";
|
|
import useImage from "use-image";
|
|
|
|
type TransformableImageConfig = Omit<ImageConfig, "image"> & {
|
|
imageUrl: string;
|
|
};
|
|
|
|
export type TransformableImageProps = {
|
|
imageProps: TransformableImageConfig;
|
|
id: string;
|
|
isSelected: boolean;
|
|
onSelect: () => void;
|
|
onChange: (newAttrs: TransformableImageConfig) => void;
|
|
};
|
|
|
|
export const TransformableImage = ({
|
|
imageProps,
|
|
id,
|
|
isSelected,
|
|
onSelect,
|
|
onChange,
|
|
}: TransformableImageProps) => {
|
|
const imageRef = useRef<ElementRef<typeof Image>>(null);
|
|
const trRef = useRef<ElementRef<typeof Transformer>>(null);
|
|
const [image] = useImage(imageProps.imageUrl);
|
|
|
|
useEffect(() => {
|
|
if (!imageRef.current) return;
|
|
|
|
if (isSelected) {
|
|
// we need to attach transformer manually
|
|
trRef.current?.nodes([imageRef.current]);
|
|
trRef.current?.getLayer()?.batchDraw();
|
|
}
|
|
}, [isSelected]);
|
|
|
|
return (
|
|
<>
|
|
<Image
|
|
id={id}
|
|
alt={"canvas image"}
|
|
onClick={onSelect}
|
|
onTap={onSelect}
|
|
ref={imageRef}
|
|
{...imageProps}
|
|
image={image}
|
|
draggable
|
|
onDragEnd={(e) => {
|
|
onChange({
|
|
...imageProps,
|
|
image,
|
|
x: e.target.x(),
|
|
y: e.target.y(),
|
|
});
|
|
}}
|
|
onTransformEnd={() => {
|
|
const node = imageRef.current;
|
|
if (!node) return;
|
|
|
|
const scaleX = node.scaleX();
|
|
const scaleY = node.scaleY();
|
|
|
|
// we will reset it back
|
|
node.scaleX(1);
|
|
node.scaleY(1);
|
|
onChange({
|
|
...imageProps,
|
|
image,
|
|
x: node.x(),
|
|
y: node.y(),
|
|
// set minimal value
|
|
width: Math.max(5, node.width() * scaleX),
|
|
height: Math.max(node.height() * scaleY),
|
|
});
|
|
}}
|
|
/>
|
|
{isSelected && (
|
|
<Transformer
|
|
ref={trRef}
|
|
boundBoxFunc={(oldBox, newBox) => {
|
|
// limit resize
|
|
if (newBox.width < 5 || newBox.height < 5) {
|
|
return oldBox;
|
|
}
|
|
return newBox;
|
|
}}
|
|
/>
|
|
)}
|
|
</>
|
|
);
|
|
};
|