aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/imageEditor/imageMeshTool/imageMesh.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/imageEditor/imageMeshTool/imageMesh.tsx')
-rw-r--r--src/client/views/nodes/imageEditor/imageMeshTool/imageMesh.tsx109
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;