My submission to a Complex Interactions Technical Assignment, where the goal was to build an interactive crop editor.
The main challenge: keeping the image fully covering the crop area through any pan, rotate, or scale — and conversely, letting the crop area resize freely, always within the image bounds.
Try it here
Steps:
- Clone/download the repository
- Run
npm installat its root to install dependencies - Run
npm run devto start the development server - Open the displayed URL in a browser
Running npm run host will expose the app to the local network, which is useful for testing on a mobile device. Touch input is fully supported and worth trying out.
Here are a few deliberate implementation choices I made:
-
Two-finger gesture handling: The editor performs scaling and rotation simultaneously during two-finger gestures. Where SCRL chooses at the beginning of the gesture whether it should be scale-only or rotation-only, my version applies both scale and rotation continuously, so each touched point stays under their respective finger. I felt this would be more intuitive for the user, while also removing the need to implement gesture disambiguation thresholds.
-
Auto-scaling during rotation: When rotating the image, automatic scaling is applied only as needed, so the crop rectangle remains fully covered at the current angle; this is one of the key requirements. While dragging the rotation control, the image may need to temporarily scale up depending on the angle, but the final scale is committed only when the interaction ends. This avoids unnecessary scaling as observed on SCRL when the slider rotation merely passes through intermediate angles.
-
Edge case near right angles: Rotation angles very close to multiples of 90° (e.g. 90.001°) can cause the edges of the crop rectangle to seem parallel to the rotated image bounds while they actually still intersect. This intersection naturally prevents the crop rectangle from expanding, but since it's invisible, the handles feel unresponsive or inconsistent as a result. I chose to address this by rounding the rotation angle to the nearest half degree, only in this situation.
While the scope of this assignment was to deliver a minimal functional prototype, I used these details to demonstrate attention to small UX considerations and experience handling interaction and UI constraints.
This work was created as a technical assignment submission. It is not intended for production use or redistribution.
The sample image is graciously provided by Deepak Nautiyal under the Unsplash license.
