From bf883a604aacca01eb5a1a00e7dd6aecded7ee89 Mon Sep 17 00:00:00 2001 From: Paulo Menezes Date: Sat, 4 Jan 2020 15:03:24 -0300 Subject: [PATCH] Detect collision with squares --- src/index.tsx | 172 +++++++++++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 73 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 2b5912795..37b99cb80 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -170,39 +170,33 @@ function hitTest(element: ExcalidrawElement, x: number, y: number): boolean { } } -function distance(x1: number, x2: number, y1: number, y2: number) { - return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); -} - function resizeTest( element: ExcalidrawElement, x: number, - y: number + y: number, + sceneState: SceneState ): string | false { - // For shapes that are composed of lines, we only enable point-selection when the distance - // of the click is less than x pixels of any of the lines that the shape is composed of - const lineThreshold = 20; - const x1 = getElementAbsoluteX1(element); const x2 = getElementAbsoluteX2(element); const y1 = getElementAbsoluteY1(element); const y2 = getElementAbsoluteY2(element); - const hx = x1 + (x2 - x1) / 2; - const hy = y1 + (y2 - y1) / 2; + const handlers = handlerRectangles(x1, x2, y1, y2, sceneState); - // (x1, y1) --A-- (x2, y1) - // |D |B - // (x1, y2) --C-- (x2, y2) - if (distance(x, hx - 5, y, y1 - 5) < lineThreshold) return "n"; - if (distance(x, x1 + 5, y, hy - 5) < lineThreshold) return "w"; - if (distance(x, x2 + 5, y, hy + 5) < lineThreshold) return "e"; - if (distance(x, hx + 5, y, y2 + 5) < lineThreshold) return "s"; + const filter = Object.keys(handlers).filter(key => { + const handler = handlers[key]; - if (distance(x, x1 - 5, y, y1 - 5) < lineThreshold) return "nw"; - if (distance(x, x2 + 5, y, y1 - 5) < lineThreshold) return "ne"; - if (distance(x, x1 + 5, y, y2 + 5) < lineThreshold) return "sw"; - if (distance(x, x2 + 5, y, y2 + 5) < lineThreshold) return "se"; + return ( + x + sceneState.scrollX >= handler[0] && + x + sceneState.scrollX <= handler[0] + handler[2] && + y + sceneState.scrollY >= handler[1] && + y + sceneState.scrollY <= handler[1] + handler[3] + ); + }); + + if (filter.length > 0) { + return filter[0]; + } return false; } @@ -280,6 +274,69 @@ function getScrollbars( }; } +function handlerRectangles( + elementX1: number, + elementX2: number, + elementY1: number, + elementY2: number, + sceneState: SceneState +) { + const margin = 4; + const handlers: { [handler: string]: number[] } = {}; + + handlers["n"] = [ + elementX1 + (elementX2 - elementX1) / 2 + sceneState.scrollX - 4, + elementY1 - margin + sceneState.scrollY - 8, + 8, + 8 + ]; // n + handlers["w"] = [ + elementX1 - margin + sceneState.scrollX - 8, + elementY1 + (elementY2 - elementY1) / 2 + sceneState.scrollY - 4, + 8, + 8 + ]; // w + handlers["e"] = [ + elementX2 - margin + sceneState.scrollX + 8, + elementY1 + (elementY2 - elementY1) / 2 + sceneState.scrollY - 4, + 8, + 8 + ]; // e + handlers["s"] = [ + elementX1 + (elementX2 - elementX1) / 2 + sceneState.scrollX - 4, + elementY2 - margin + sceneState.scrollY + 8, + 8, + 8 + ]; // s + + handlers["nw"] = [ + elementX1 - margin + sceneState.scrollX - 8, + elementY1 - margin + sceneState.scrollY - 8, + 8, + 8 + ]; // nw + handlers["ne"] = [ + elementX2 - margin + sceneState.scrollX + 8, + elementY1 - margin + sceneState.scrollY - 8, + 8, + 8 + ]; // ne + handlers["sw"] = [ + elementX1 - margin + sceneState.scrollX - 8, + elementY2 - margin + sceneState.scrollY + 8, + 8, + 8 + ]; // sw + handlers["se"] = [ + elementX2 - margin + sceneState.scrollX + 8, + elementY2 - margin + sceneState.scrollY + 8, + 8, + 8 + ]; // se + + return handlers; +} + function renderScene( rc: RoughCanvas, context: CanvasRenderingContext2D, @@ -315,55 +372,16 @@ function renderScene( ); context.setLineDash(lineDash); - context.strokeRect( - elementX1 + (elementX2 - elementX1) / 2 + sceneState.scrollX - 4, - elementY1 - margin + sceneState.scrollY - 8, - 8, - 8 - ); // n - context.strokeRect( - elementX1 - margin + sceneState.scrollX - 8, - elementY1 + (elementY2 - elementY1) / 2 + sceneState.scrollY - 4, - 8, - 8 - ); // w - context.strokeRect( - elementX2 - margin + sceneState.scrollX + 8, - elementY1 + (elementY2 - elementY1) / 2 + sceneState.scrollY - 4, - 8, - 8 - ); // e - context.strokeRect( - elementX1 + (elementX2 - elementX1) / 2 + sceneState.scrollX - 4, - elementY2 - margin + sceneState.scrollY + 8, - 8, - 8 - ); // s - - context.strokeRect( - elementX1 - margin + sceneState.scrollX - 8, - elementY1 - margin + sceneState.scrollY - 8, - 8, - 8 - ); // nw - context.strokeRect( - elementX2 - margin + sceneState.scrollX + 8, - elementY1 - margin + sceneState.scrollY - 8, - 8, - 8 - ); // ne - context.strokeRect( - elementX1 - margin + sceneState.scrollX - 8, - elementY2 - margin + sceneState.scrollY + 8, - 8, - 8 - ); // sw - context.strokeRect( - elementX2 - margin + sceneState.scrollX + 8, - elementY2 - margin + sceneState.scrollY + 8, - 8, - 8 - ); // se + const handlers = handlerRectangles( + elementX1, + elementX2, + elementY1, + elementY2, + sceneState + ); + Object.values(handlers).forEach(handler => { + context.strokeRect(handler[0], handler[1], handler[2], handler[3]); + }); } }); @@ -1113,7 +1131,11 @@ class App extends React.Component<{}, AppState> { const cursorStyle = document.documentElement.style.cursor; if (this.state.elementType === "selection") { const resizeElement = elements.find(element => { - return resizeTest(element, x, y); + return resizeTest(element, x, y, { + scrollX: this.state.scrollX, + scrollY: this.state.scrollY, + viewBackgroundColor: this.state.viewBackgroundColor + }); }); this.setState({ @@ -1121,7 +1143,11 @@ class App extends React.Component<{}, AppState> { }); if (resizeElement) { - resizeHandle = resizeTest(resizeElement, x, y); + resizeHandle = resizeTest(resizeElement, x, y, { + scrollX: this.state.scrollX, + scrollY: this.state.scrollY, + viewBackgroundColor: this.state.viewBackgroundColor + }); document.documentElement.style.cursor = `${resizeHandle}-resize`; isResizingElements = true; }