I have a problem making a rectangle which can be dragged and resized over an image in react native using PanResponder. The resizing works like a charm however I cannot drag the rectangle, in the console it logs “Dragging…” but it does not drag, this seems to be a problem with:
setCropRegion((prev) => ({ ...prev, x: Math.max(0, Math.min(prev.x + dx, imageSize.width - prev.width)), y: Math.max(0, Math.min(prev.y + dy, imageSize.height - prev.height)), }));
When I remove “imageSize.width -” and “imageSize.height -” it can be dragged, but then only very weirdly and exponentially resizes up. Btw all the useEffects have to be there, otherwise the state won’t update
Full code:
`
function Resize() {
const image = “…PATH…”;
const [cropRegion, setCropRegion] = useState({ x: 0, y: 0, width: 50, height: 50 });
const [isDragging, setIsDragging] = useState(false);
const [imageSize, setImageSize] = useState({ width: 0, height: 0 });
const cropRegionRef = useRef(cropRegion);
const isDraggingRef = useRef(isDragging);
const imageRef = useRef(null);
const onImageLayout = (layout) => {
setImageSize({
width: layout.nativeEvent.layout.width,
height: layout.nativeEvent.layout.height,
}); // this works, 300px = width, 700px = height
};
useEffect(() => {
cropRegionRef.current = cropRegion;
}, [cropRegion]);
useEffect(() => {
isDraggingRef.current = isDragging;
}, [isDragging]);
const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderGrant: (e, gestureState) => {
const { x0, y0 } = gestureState;
const withinCropBox =
x0 >= cropRegionRef.current.x &&
x0 <= cropRegionRef.current.x + cropRegionRef.current.width &&
y0 >= cropRegionRef.current.y &&
y0 <= cropRegionRef.current.y + cropRegionRef.current.height;
console.log("grant ", withinCropBox);
if (withinCropBox) {
setIsDragging(true);
}
},
onPanResponderMove: (e, gestureState) => {
const { dx, dy, moveX, moveY } = gestureState;
if (isDraggingRef.current) {
console.log("dragging....");
setCropRegion((prev) => ({
...prev,
x: Math.max(
0,
Math.min(prev.x + dx, imageSize.width - prev.width),
),
y: Math.max(
0,
Math.min(prev.y + dy, imageSize.height - prev.height),
),
}));
} else {
console.log("resizing...");
setCropRegion((prev) => ({
...prev,
width: Math.max(0, moveX - prev.x),
height: Math.max(0, moveY - prev.y),
}));
}
},
onPanResponderRelease: () => {
console.log("releasing...");
setIsDragging(false);
},
}),
).current;
return (
<SafeAreaView className="bg-cloud flex flex-col h-full">
<View
className="relative h-full"
{...panResponder.panHandlers}
ref={imageRef}
onLayout={onImageLayout}
>
<Image
source={{ uri: image }}
style={{ width: "100%", height: "100%" }}
/>
<View
className="absolute border-2 border-red-400"
style={{
left: cropRegion.x,
top: cropRegion.y,
width: cropRegion.width,
height: cropRegion.height,
}}
/>
</View>
</SafeAreaView>
);
}
`
I already tried other mathematical formulas, all which didn’t work.