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 & { 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>(null); const trRef = useRef>(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 ( <> {"canvas { 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 && ( { // limit resize if (newBox.width < 5 || newBox.height < 5) { return oldBox; } return newBox; }} /> )} ); };