1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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;
|