diff options
Diffstat (limited to 'src/client/views/nodes/imageEditor/imageMeshTool/imageMesh.tsx')
-rw-r--r-- | src/client/views/nodes/imageEditor/imageMeshTool/imageMesh.tsx | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/client/views/nodes/imageEditor/imageMeshTool/imageMesh.tsx b/src/client/views/nodes/imageEditor/imageMeshTool/imageMesh.tsx new file mode 100644 index 000000000..ee5c597e9 --- /dev/null +++ b/src/client/views/nodes/imageEditor/imageMeshTool/imageMesh.tsx @@ -0,0 +1,109 @@ +import React, { useState, useEffect } from 'react'; +import './MeshTransformGrid.scss'; + +interface MeshTransformGridProps { + imageRef: React.RefObject<HTMLImageElement>; // Reference to the image element + gridXSize: number; // Number of X subdivisions + gridYSize: number; // Number of Y subdivisions + isInteractive: boolean; // Whether control points are interactive (can be dragged) +} + +const MeshTransformGrid: React.FC<MeshTransformGridProps> = ({ imageRef, gridXSize, gridYSize, isInteractive }) => { + const [controlPoints, setControlPoints] = useState<any[]>([]); + + // Set up control points based on image size and grid sizes + useEffect(() => { + if (imageRef.current) { + const { width, height, left, top } = imageRef.current.getBoundingClientRect(); + const newControlPoints = []; + + for (let i = 0; i <= gridYSize; i++) { + for (let j = 0; j <= gridXSize; j++) { + newControlPoints.push({ + id: `${i}-${j}`, + x: (j * width) / gridXSize + left, + y: (i * height) / gridYSize + top, + }); + } + } + + setControlPoints(newControlPoints); + } + }, [imageRef, gridXSize, gridYSize]); + + // Handle dragging of control points + const handleDrag = (e: React.MouseEvent, pointId: string) => { + if (!isInteractive) return; // Prevent dragging if grid is not interactive + + const { clientX, clientY } = e; + const updatedPoints = controlPoints.map((point) => { + if (point.id === pointId) { + return { ...point, x: clientX, y: clientY }; + } + return point; + }); + setControlPoints(updatedPoints); + }; + + // Render grid lines between control points + const renderGridLines = () => { + const lines = []; + for (let i = 0; i < controlPoints.length; i++) { + const point = controlPoints[i]; + const nextPoint = controlPoints[i + 1]; + + // Horizontal lines + if (nextPoint && i % (gridXSize + 1) !== gridXSize) { + lines.push({ + start: { x: point.x, y: point.y }, + end: { x: nextPoint.x, y: nextPoint.y }, + }); + } + + // Vertical lines + if (i + gridXSize + 1 < controlPoints.length) { + const downPoint = controlPoints[i + gridXSize + 1]; + lines.push({ + start: { x: point.x, y: point.y }, + end: { x: downPoint.x, y: downPoint.y }, + }); + } + } + return lines.map((line, index) => ( + <div + key={index} + className="grid-line" + style={{ + position: 'absolute', + left: `${line.start.x}px`, + top: `${line.start.y}px`, + width: `${Math.abs(line.end.x - line.start.x)}px`, + height: `${Math.abs(line.end.y - line.start.y)}px`, + border: '1px solid rgba(255, 255, 255, 0.6)', + }} + /> + )); + }; + + return ( + <div className="meshTransformGrid"> + {renderGridLines()} + + {controlPoints.map((point) => ( + <div + key={point.id} + className="control-point" + style={{ + left: `${point.x}px`, + top: `${point.y}px`, + transform: 'translate(-50%, -50%)', + }} + draggable={isInteractive} // Only allow dragging if interactive + onDrag={(e) => handleDrag(e, point.id)} + /> + ))} + </div> + ); +}; + +export default MeshTransformGrid; |