123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- import { ExcalidrawElement } from "../element/types";
- import { getCommonBounds } from "../element";
- import { FlooredNumber } from "../types";
- import { ScrollBars } from "./types";
- import { getGlobalCSSVariable } from "../utils";
- export 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[],
- viewportWidth: number,
- viewportHeight: number,
- {
- scrollX,
- scrollY,
- zoom,
- }: {
- scrollX: FlooredNumber;
- scrollY: FlooredNumber;
- zoom: number;
- },
- ): ScrollBars {
- // This is the bounding box of all the elements
- const [
- elementsMinX,
- elementsMinY,
- elementsMaxX,
- elementsMaxY,
- ] = getCommonBounds(elements);
- // Apply zoom
- const viewportWidthWithZoom = viewportWidth / zoom;
- const viewportHeightWithZoom = viewportHeight / zoom;
- const viewportWidthDiff = viewportWidth - viewportWidthWithZoom;
- const viewportHeightDiff = viewportHeight - viewportHeightWithZoom;
- const safeArea = {
- top: parseInt(getGlobalCSSVariable("sat")),
- bottom: parseInt(getGlobalCSSVariable("sab")),
- left: parseInt(getGlobalCSSVariable("sal")),
- right: parseInt(getGlobalCSSVariable("sar")),
- };
- // The viewport is the rectangle currently visible for the user
- 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;
- // 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);
- // The scrollbar represents where the viewport is in relationship to the scene
- return {
- horizontal:
- viewportMinX === sceneMinX && viewportMaxX === sceneMaxX
- ? null
- : {
- x:
- Math.max(safeArea.left, SCROLLBAR_MARGIN) +
- ((viewportMinX - sceneMinX) / (sceneMaxX - sceneMinX)) *
- viewportWidth,
- y:
- viewportHeight -
- SCROLLBAR_WIDTH -
- Math.max(SCROLLBAR_MARGIN, safeArea.bottom),
- width:
- ((viewportMaxX - viewportMinX) / (sceneMaxX - sceneMinX)) *
- viewportWidth -
- Math.max(SCROLLBAR_MARGIN * 2, safeArea.left + safeArea.right),
- height: SCROLLBAR_WIDTH,
- },
- vertical:
- viewportMinY === sceneMinY && viewportMaxY === sceneMaxY
- ? null
- : {
- x:
- viewportWidth -
- SCROLLBAR_WIDTH -
- Math.max(safeArea.right, SCROLLBAR_MARGIN),
- y:
- ((viewportMinY - sceneMinY) / (sceneMaxY - sceneMinY)) *
- viewportHeight +
- Math.max(safeArea.top, SCROLLBAR_MARGIN),
- width: SCROLLBAR_WIDTH,
- height:
- ((viewportMaxY - viewportMinY) / (sceneMaxY - sceneMinY)) *
- viewportHeight -
- Math.max(SCROLLBAR_MARGIN * 2, safeArea.top + safeArea.bottom),
- },
- };
- }
- export function isOverScrollBars(scrollBars: ScrollBars, x: number, y: number) {
- const [isOverHorizontalScrollBar, isOverVerticalScrollBar] = [
- scrollBars.horizontal,
- scrollBars.vertical,
- ].map((scrollBar) => {
- return (
- scrollBar &&
- scrollBar.x <= x &&
- x <= scrollBar.x + scrollBar.width &&
- scrollBar.y <= y &&
- y <= scrollBar.y + scrollBar.height
- );
- });
- return {
- isOverHorizontalScrollBar,
- isOverVerticalScrollBar,
- };
- }
|