Skip to content

Commit

Permalink
feat (feedback) - Make cropped screenshot area draggable (#13071)
Browse files Browse the repository at this point in the history
- [x] If you've added code that should be tested, please add tests.
- [x] Ensure your code lints and the test suite passes (`yarn lint`) &
(`yarn test`).fe

This addition adds an intuitive way to resize screenshots in the user
feedback widget. The draggable area is bound by the canvas box (so it
won't overflow) and is only draggable when cropped (when confirm/cancel
buttons present)


https://github.com/user-attachments/assets/7ddff991-a791-4d41-a2ad-b278e1ab4950
  • Loading branch information
joemmalatesta committed Jul 26, 2024
1 parent 5c03ac5 commit a880712
Showing 1 changed file with 58 additions and 1 deletion.
59 changes: 58 additions & 1 deletion packages/feedback/src/screenshot/components/ScreenshotEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export function ScreenshotEditorFactory({
const croppingRef = hooks.useRef<HTMLCanvasElement>(null);
const [croppingRect, setCroppingRect] = hooks.useState<Box>({ startX: 0, startY: 0, endX: 0, endY: 0 });
const [confirmCrop, setConfirmCrop] = hooks.useState(false);
const [isResizing, setIsResizing] = hooks.useState(false);

hooks.useEffect(() => {
WINDOW.addEventListener('resize', resizeCropper, false);
Expand Down Expand Up @@ -141,11 +142,13 @@ export function ScreenshotEditorFactory({

function onGrabButton(e: Event, corner: string): void {
setConfirmCrop(false);
setIsResizing(true);
const handleMouseMove = makeHandleMouseMove(corner);
const handleMouseUp = (): void => {
DOCUMENT.removeEventListener('mousemove', handleMouseMove);
DOCUMENT.removeEventListener('mouseup', handleMouseUp);
setConfirmCrop(true);
setIsResizing(false);
};

DOCUMENT.addEventListener('mouseup', handleMouseUp);
Expand Down Expand Up @@ -194,6 +197,56 @@ export function ScreenshotEditorFactory({
};
}, []);

// DRAGGING FUNCTIONALITY.
const initialPositionRef = hooks.useRef({ initialX: 0, initialY: 0 });

function onDragStart(e: MouseEvent): void {
if (isResizing) return;

initialPositionRef.current = { initialX: e.clientX, initialY: e.clientY };

const handleMouseMove = (moveEvent: MouseEvent): void => {
const cropCanvas = croppingRef.current;
if (!cropCanvas) return;

const deltaX = moveEvent.clientX - initialPositionRef.current.initialX;
const deltaY = moveEvent.clientY - initialPositionRef.current.initialY;

setCroppingRect(prev => {
// Math.max stops it from going outside of the borders
const newStartX = Math.max(
0,
Math.min(prev.startX + deltaX, cropCanvas.width / DPI - (prev.endX - prev.startX)),
);
const newStartY = Math.max(
0,
Math.min(prev.startY + deltaY, cropCanvas.height / DPI - (prev.endY - prev.startY)),
);
// Don't want to change size, just position
const newEndX = newStartX + (prev.endX - prev.startX);
const newEndY = newStartY + (prev.endY - prev.startY);

initialPositionRef.current.initialX = moveEvent.clientX;
initialPositionRef.current.initialY = moveEvent.clientY;

return {
startX: newStartX,
startY: newStartY,
endX: newEndX,
endY: newEndY,
};
});
};

const handleMouseUp = (): void => {
DOCUMENT.removeEventListener('mousemove', handleMouseMove);
DOCUMENT.removeEventListener('mouseup', handleMouseUp);
};

DOCUMENT.addEventListener('mousemove', handleMouseMove);
DOCUMENT.addEventListener('mouseup', handleMouseUp);
}

function submit(): void {
const cutoutCanvas = DOCUMENT.createElement('canvas');
const imageBox = constructRect(getContainedSize(imageBuffer));
Expand Down Expand Up @@ -263,7 +316,11 @@ export function ScreenshotEditorFactory({
<style dangerouslySetInnerHTML={styles} />
<div class="editor__canvas-container" ref={canvasContainerRef}>
<div class="editor__crop-container" style={{ position: 'absolute', zIndex: 1 }} ref={cropContainerRef}>
<canvas style={{ position: 'absolute' }} ref={croppingRef}></canvas>
<canvas
onMouseDown={onDragStart}
style={{ position: 'absolute', cursor: confirmCrop ? 'move' : 'auto' }}
ref={croppingRef}
></canvas>
<CropCorner
left={croppingRect.startX - CROP_BUTTON_BORDER}
top={croppingRect.startY - CROP_BUTTON_BORDER}
Expand Down

0 comments on commit a880712

Please sign in to comment.