excalidraw/src/scene/scrollbars.ts
Gasim Gasimzada 862231da4f Make all operations on elements array immutable (#283)
* Make scene functions return array instead of mutate array

- Not all functions were changes; so the given argument was a new array to some

* Make data restoration functions immutable

- Make mutations in App component

* Make history actions immutable

* Fix an issue in change property that was causing elements to be removed

* mark elements params as readonly & remove unnecessary copying

* Make `clearSelection` return a new array

* Perform Id comparisons instead of reference comparisons in onDoubleClick

* Allow deselecting items with SHIFT key

- Refactor hit detection code

* Fix a bug in element selection and revert drag functionality

Co-authored-by: David Luzar <luzar.david@gmail.com>
2020-01-09 16:22:04 +01:00

112 lines
2.7 KiB
TypeScript

import { ExcalidrawElement } from "../element/types";
import { getElementAbsoluteCoords } from "../element";
const SCROLLBAR_MIN_SIZE = 15;
const SCROLLBAR_MARGIN = 4;
export const SCROLLBAR_WIDTH = 6;
export const SCROLLBAR_COLOR = "rgba(0,0,0,0.3)";
export function getScrollBars(
elements: readonly ExcalidrawElement[],
canvasWidth: number,
canvasHeight: number,
scrollX: number,
scrollY: number
) {
let minX = Infinity;
let maxX = 0;
let minY = Infinity;
let maxY = 0;
elements.forEach(element => {
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
minX = Math.min(minX, x1);
minY = Math.min(minY, y1);
maxX = Math.max(maxX, x2);
maxY = Math.max(maxY, y2);
});
minX += scrollX;
maxX += scrollX;
minY += scrollY;
maxY += scrollY;
const leftOverflow = Math.max(-minX, 0);
const rightOverflow = Math.max(-(canvasWidth - maxX), 0);
const topOverflow = Math.max(-minY, 0);
const bottomOverflow = Math.max(-(canvasHeight - maxY), 0);
// horizontal scrollbar
let horizontalScrollBar = null;
if (leftOverflow || rightOverflow) {
horizontalScrollBar = {
x: Math.min(
leftOverflow + SCROLLBAR_MARGIN,
canvasWidth - SCROLLBAR_MIN_SIZE - SCROLLBAR_MARGIN
),
y: canvasHeight - SCROLLBAR_WIDTH - SCROLLBAR_MARGIN,
width: Math.max(
canvasWidth - rightOverflow - leftOverflow - SCROLLBAR_MARGIN * 2,
SCROLLBAR_MIN_SIZE
),
height: SCROLLBAR_WIDTH
};
}
// vertical scrollbar
let verticalScrollBar = null;
if (topOverflow || bottomOverflow) {
verticalScrollBar = {
x: canvasWidth - SCROLLBAR_WIDTH - SCROLLBAR_MARGIN,
y: Math.min(
topOverflow + SCROLLBAR_MARGIN,
canvasHeight - SCROLLBAR_MIN_SIZE - SCROLLBAR_MARGIN
),
width: SCROLLBAR_WIDTH,
height: Math.max(
canvasHeight - bottomOverflow - topOverflow - SCROLLBAR_WIDTH * 2,
SCROLLBAR_MIN_SIZE
)
};
}
return {
horizontal: horizontalScrollBar,
vertical: verticalScrollBar
};
}
export function isOverScrollBars(
elements: readonly ExcalidrawElement[],
x: number,
y: number,
canvasWidth: number,
canvasHeight: number,
scrollX: number,
scrollY: number
) {
const scrollBars = getScrollBars(
elements,
canvasWidth,
canvasHeight,
scrollX,
scrollY
);
const [isOverHorizontalScrollBar, isOverVerticalScrollBar] = [
scrollBars.horizontal,
scrollBars.vertical
].map(
scrollBar =>
scrollBar &&
scrollBar.x <= x &&
x <= scrollBar.x + scrollBar.width &&
scrollBar.y <= y &&
y <= scrollBar.y + scrollBar.height
);
return {
isOverHorizontalScrollBar,
isOverVerticalScrollBar
};
}