2020-01-06 20:24:54 +04:00
|
|
|
import { ExcalidrawElement } from "../element/types";
|
2020-01-26 20:15:08 +01:00
|
|
|
import { getCommonBounds } from "../element";
|
2020-11-04 17:49:15 +00:00
|
|
|
import { FlooredNumber, Zoom } from "../types";
|
2020-03-01 21:43:35 +01:00
|
|
|
import { ScrollBars } from "./types";
|
2020-03-18 11:31:40 -04:00
|
|
|
import { getGlobalCSSVariable } from "../utils";
|
2020-04-02 12:21:19 -04:00
|
|
|
import { getLanguage } from "../i18n";
|
2020-01-06 20:24:54 +04:00
|
|
|
|
2020-03-18 11:31:40 -04:00
|
|
|
export const SCROLLBAR_MARGIN = 4;
|
2020-01-06 20:24:54 +04:00
|
|
|
export const SCROLLBAR_WIDTH = 6;
|
|
|
|
export const SCROLLBAR_COLOR = "rgba(0,0,0,0.3)";
|
|
|
|
|
2020-05-20 16:21:37 +03:00
|
|
|
export const getScrollBars = (
|
2020-01-09 19:22:04 +04:00
|
|
|
elements: readonly ExcalidrawElement[],
|
2020-02-08 16:20:14 -08:00
|
|
|
viewportWidth: number,
|
|
|
|
viewportHeight: number,
|
2020-02-15 21:03:32 +01:00
|
|
|
{
|
|
|
|
scrollX,
|
|
|
|
scrollY,
|
|
|
|
zoom,
|
|
|
|
}: {
|
2020-02-19 08:25:01 -08:00
|
|
|
scrollX: FlooredNumber;
|
|
|
|
scrollY: FlooredNumber;
|
2020-11-04 17:49:15 +00:00
|
|
|
zoom: Zoom;
|
2020-02-15 21:03:32 +01:00
|
|
|
},
|
2020-05-20 16:21:37 +03:00
|
|
|
): ScrollBars => {
|
2020-02-08 16:20:14 -08:00
|
|
|
// This is the bounding box of all the elements
|
|
|
|
const [
|
|
|
|
elementsMinX,
|
|
|
|
elementsMinY,
|
|
|
|
elementsMaxX,
|
|
|
|
elementsMaxY,
|
|
|
|
] = getCommonBounds(elements);
|
2020-01-06 20:24:54 +04:00
|
|
|
|
2020-02-15 21:03:32 +01:00
|
|
|
// Apply zoom
|
2020-11-04 17:49:15 +00:00
|
|
|
const viewportWidthWithZoom = viewportWidth / zoom.value;
|
|
|
|
const viewportHeightWithZoom = viewportHeight / zoom.value;
|
2020-02-15 21:03:32 +01:00
|
|
|
|
|
|
|
const viewportWidthDiff = viewportWidth - viewportWidthWithZoom;
|
|
|
|
const viewportHeightDiff = viewportHeight - viewportHeightWithZoom;
|
|
|
|
|
2020-03-18 11:31:40 -04:00
|
|
|
const safeArea = {
|
|
|
|
top: parseInt(getGlobalCSSVariable("sat")),
|
|
|
|
bottom: parseInt(getGlobalCSSVariable("sab")),
|
|
|
|
left: parseInt(getGlobalCSSVariable("sal")),
|
|
|
|
right: parseInt(getGlobalCSSVariable("sar")),
|
|
|
|
};
|
|
|
|
|
2020-04-02 12:21:19 -04:00
|
|
|
const isRTL = getLanguage().rtl;
|
|
|
|
|
2020-02-08 16:20:14 -08:00
|
|
|
// The viewport is the rectangle currently visible for the user
|
2020-03-18 11:31:40 -04:00
|
|
|
const viewportMinX = -scrollX + viewportWidthDiff / 2 + safeArea.left;
|
|
|
|
const viewportMinY = -scrollY + viewportHeightDiff / 2 + safeArea.top;
|
|
|
|
const viewportMaxX = viewportMinX + viewportWidthWithZoom - safeArea.right;
|
|
|
|
const viewportMaxY = viewportMinY + viewportHeightWithZoom - safeArea.bottom;
|
2020-01-26 20:15:08 +01:00
|
|
|
|
2020-02-08 16:20:14 -08:00
|
|
|
// The scene is the bounding box of both the elements and viewport
|
|
|
|
const sceneMinX = Math.min(elementsMinX, viewportMinX);
|
|
|
|
const sceneMinY = Math.min(elementsMinY, viewportMinY);
|
|
|
|
const sceneMaxX = Math.max(elementsMaxX, viewportMaxX);
|
|
|
|
const sceneMaxY = Math.max(elementsMaxY, viewportMaxY);
|
2020-01-06 20:24:54 +04:00
|
|
|
|
2020-02-08 16:20:14 -08:00
|
|
|
// The scrollbar represents where the viewport is in relationship to the scene
|
2020-01-06 20:24:54 +04:00
|
|
|
|
|
|
|
return {
|
2020-02-08 16:20:14 -08:00
|
|
|
horizontal:
|
|
|
|
viewportMinX === sceneMinX && viewportMaxX === sceneMaxX
|
|
|
|
? null
|
|
|
|
: {
|
|
|
|
x:
|
2020-03-18 11:31:40 -04:00
|
|
|
Math.max(safeArea.left, SCROLLBAR_MARGIN) +
|
2020-02-08 16:20:14 -08:00
|
|
|
((viewportMinX - sceneMinX) / (sceneMaxX - sceneMinX)) *
|
2020-03-18 11:31:40 -04:00
|
|
|
viewportWidth,
|
|
|
|
y:
|
|
|
|
viewportHeight -
|
|
|
|
SCROLLBAR_WIDTH -
|
|
|
|
Math.max(SCROLLBAR_MARGIN, safeArea.bottom),
|
2020-02-08 16:20:14 -08:00
|
|
|
width:
|
|
|
|
((viewportMaxX - viewportMinX) / (sceneMaxX - sceneMinX)) *
|
|
|
|
viewportWidth -
|
2020-03-18 11:31:40 -04:00
|
|
|
Math.max(SCROLLBAR_MARGIN * 2, safeArea.left + safeArea.right),
|
2020-02-08 16:20:14 -08:00
|
|
|
height: SCROLLBAR_WIDTH,
|
|
|
|
},
|
|
|
|
vertical:
|
|
|
|
viewportMinY === sceneMinY && viewportMaxY === sceneMaxY
|
|
|
|
? null
|
|
|
|
: {
|
2020-04-02 12:21:19 -04:00
|
|
|
x: isRTL
|
|
|
|
? Math.max(safeArea.left, SCROLLBAR_MARGIN)
|
|
|
|
: viewportWidth -
|
|
|
|
SCROLLBAR_WIDTH -
|
|
|
|
Math.max(safeArea.right, SCROLLBAR_MARGIN),
|
2020-02-08 16:20:14 -08:00
|
|
|
y:
|
|
|
|
((viewportMinY - sceneMinY) / (sceneMaxY - sceneMinY)) *
|
|
|
|
viewportHeight +
|
2020-03-18 11:31:40 -04:00
|
|
|
Math.max(safeArea.top, SCROLLBAR_MARGIN),
|
2020-02-08 16:20:14 -08:00
|
|
|
width: SCROLLBAR_WIDTH,
|
|
|
|
height:
|
|
|
|
((viewportMaxY - viewportMinY) / (sceneMaxY - sceneMinY)) *
|
|
|
|
viewportHeight -
|
2020-03-18 11:31:40 -04:00
|
|
|
Math.max(SCROLLBAR_MARGIN * 2, safeArea.top + safeArea.bottom),
|
2020-02-08 16:20:14 -08:00
|
|
|
},
|
2020-01-06 20:24:54 +04:00
|
|
|
};
|
2020-05-20 16:21:37 +03:00
|
|
|
};
|
2020-01-06 20:24:54 +04:00
|
|
|
|
2020-05-20 16:21:37 +03:00
|
|
|
export const isOverScrollBars = (
|
|
|
|
scrollBars: ScrollBars,
|
|
|
|
x: number,
|
|
|
|
y: number,
|
2020-07-08 22:07:51 -07:00
|
|
|
): {
|
2020-07-09 14:15:42 -07:00
|
|
|
isOverEither: boolean;
|
|
|
|
isOverHorizontal: boolean;
|
|
|
|
isOverVertical: boolean;
|
2020-07-08 22:07:51 -07:00
|
|
|
} => {
|
2020-07-09 14:15:42 -07:00
|
|
|
const [isOverHorizontal, isOverVertical] = [
|
2020-01-06 20:24:54 +04:00
|
|
|
scrollBars.horizontal,
|
2020-01-24 12:04:54 +02:00
|
|
|
scrollBars.vertical,
|
2020-03-23 13:05:07 +02:00
|
|
|
].map((scrollBar) => {
|
2020-02-08 16:20:14 -08:00
|
|
|
return (
|
2020-07-08 22:07:51 -07:00
|
|
|
scrollBar != null &&
|
2020-01-06 20:24:54 +04:00
|
|
|
scrollBar.x <= x &&
|
|
|
|
x <= scrollBar.x + scrollBar.width &&
|
|
|
|
scrollBar.y <= y &&
|
2020-02-08 16:20:14 -08:00
|
|
|
y <= scrollBar.y + scrollBar.height
|
|
|
|
);
|
|
|
|
});
|
2020-07-09 14:15:42 -07:00
|
|
|
const isOverEither = isOverHorizontal || isOverVertical;
|
|
|
|
return { isOverEither, isOverHorizontal, isOverVertical };
|
2020-05-20 16:21:37 +03:00
|
|
|
};
|