You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

52 lines
1.5 KiB

2 months ago
  1. // @flow
  2. import type { ClientRectObject, VirtualElement } from '../types';
  3. import { isElement, isHTMLElement } from './instanceOf';
  4. import { round } from '../utils/math';
  5. import getWindow from './getWindow';
  6. import isLayoutViewport from './isLayoutViewport';
  7. export default function getBoundingClientRect(
  8. element: Element | VirtualElement,
  9. includeScale: boolean = false,
  10. isFixedStrategy: boolean = false
  11. ): ClientRectObject {
  12. const clientRect = element.getBoundingClientRect();
  13. let scaleX = 1;
  14. let scaleY = 1;
  15. if (includeScale && isHTMLElement(element)) {
  16. scaleX =
  17. (element: HTMLElement).offsetWidth > 0
  18. ? round(clientRect.width) / (element: HTMLElement).offsetWidth || 1
  19. : 1;
  20. scaleY =
  21. (element: HTMLElement).offsetHeight > 0
  22. ? round(clientRect.height) / (element: HTMLElement).offsetHeight || 1
  23. : 1;
  24. }
  25. const { visualViewport } = isElement(element) ? getWindow(element) : window;
  26. const addVisualOffsets = !isLayoutViewport() && isFixedStrategy;
  27. const x =
  28. (clientRect.left +
  29. (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) /
  30. scaleX;
  31. const y =
  32. (clientRect.top +
  33. (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) /
  34. scaleY;
  35. const width = clientRect.width / scaleX;
  36. const height = clientRect.height / scaleY;
  37. return {
  38. width,
  39. height,
  40. top: y,
  41. right: x + width,
  42. bottom: y + height,
  43. left: x,
  44. x,
  45. y,
  46. };
  47. }