Files
dpage-editor/src/pages/editor/components/tools/ImageObject.tsx
T
2026-07-05 15:52:39 +03:30

135 lines
3.9 KiB
TypeScript

import { useEffect, useRef } from "react";
import { Image as KonvaImage, Group, Rect } from "react-konva";
import Konva from "konva";
import useImage from "use-image";
import type { ShapeProps } from "./types";
import { clampPositionToStage } from "../../utils/stageBounds";
import { createRoundedRectClipFunc, getObjectBorderRadius } from "../../utils/borderRadius";
const ImageObject = ({
obj,
isSelected,
onSelect,
onUpdate,
draggable,
stageWidth,
stageHeight,
onImageReady,
}: ShapeProps) => {
const [image, status] = useImage(obj.imageUrl || "");
const shapeRef = useRef<Konva.Image>(null);
const groupRef = useRef<Konva.Group>(null);
useEffect(() => {
if (status === "loaded" && onImageReady) {
onImageReady();
}
}, [status, onImageReady]);
if (!image) return null;
const width = obj.width || image.width;
const height = obj.height || image.height;
const hasStageBounds = stageWidth != null && stageHeight != null;
const cornerRadius = getObjectBorderRadius(obj.borderRadius);
const clipFunc = createRoundedRectClipFunc(width, height, cornerRadius);
const dragBoundFunc =
draggable && hasStageBounds
? (pos: { x: number; y: number }) =>
clampPositionToStage(
pos.x,
pos.y,
width,
height,
stageWidth!,
stageHeight!,
)
: undefined;
const handleDragEnd = (e: Konva.KonvaEventObject<DragEvent>) => {
const node = e.target;
let x = node.x();
let y = node.y();
if (hasStageBounds) {
({ x, y } = clampPositionToStage(
x,
y,
width,
height,
stageWidth!,
stageHeight!,
));
node.position({ x, y });
}
onUpdate(obj.id, { x, y });
};
const handleClick = (e: Konva.KonvaEventObject<MouseEvent>) => {
const node = cornerRadius > 0 ? groupRef.current : shapeRef.current;
if (node) {
onSelect(obj.id, node, e);
}
};
if (cornerRadius > 0) {
return (
<Group
ref={groupRef}
id={obj.id}
name="canvas-object"
x={obj.x}
y={obj.y}
rotation={obj.rotation || 0}
draggable={draggable}
clipFunc={clipFunc}
dragBoundFunc={dragBoundFunc}
onClick={handleClick}
onDragEnd={handleDragEnd}
>
<KonvaImage
x={0}
y={0}
image={image}
width={width}
height={height}
/>
{isSelected && (
<Rect
x={0}
y={0}
width={width}
height={height}
stroke="#3b82f6"
strokeWidth={3}
cornerRadius={cornerRadius}
listening={false}
/>
)}
</Group>
);
}
return (
<KonvaImage
ref={shapeRef}
id={obj.id}
name="canvas-object"
x={obj.x}
y={obj.y}
image={image}
width={width}
height={height}
stroke={isSelected ? "#3b82f6" : undefined}
strokeWidth={isSelected ? 3 : 0}
rotation={obj.rotation || 0}
draggable={draggable}
dragBoundFunc={dragBoundFunc}
onClick={handleClick}
onDragEnd={handleDragEnd}
/>
);
};
export default ImageObject;