index.mjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. /**
  2. * Observes an element's rectangle on screen (getBoundingClientRect)
  3. * This is useful to track elements on the screen and attach other elements
  4. * that might be in different layers, etc.
  5. */ function $0f3bbd680c63c15c$export$5a50ff2cde8c3802(/** The element whose rect to observe */ elementToObserve, /** The callback which will be called when the rect changes */ callback) {
  6. const observedData1 = $0f3bbd680c63c15c$var$observedElements.get(elementToObserve);
  7. if (observedData1 === undefined) {
  8. // add the element to the map of observed elements with its first callback
  9. // because this is the first time this element is observed
  10. $0f3bbd680c63c15c$var$observedElements.set(elementToObserve, {
  11. rect: {},
  12. callbacks: [
  13. callback
  14. ]
  15. });
  16. if ($0f3bbd680c63c15c$var$observedElements.size === 1) // start the internal loop once at least 1 element is observed
  17. $0f3bbd680c63c15c$var$rafId = requestAnimationFrame($0f3bbd680c63c15c$var$runLoop);
  18. } else {
  19. // only add a callback for this element as it's already observed
  20. observedData1.callbacks.push(callback);
  21. callback(elementToObserve.getBoundingClientRect());
  22. }
  23. return ()=>{
  24. const observedData = $0f3bbd680c63c15c$var$observedElements.get(elementToObserve);
  25. if (observedData === undefined) return; // start by removing the callback
  26. const index = observedData.callbacks.indexOf(callback);
  27. if (index > -1) observedData.callbacks.splice(index, 1);
  28. if (observedData.callbacks.length === 0) {
  29. // stop observing this element because there are no
  30. // callbacks registered for it anymore
  31. $0f3bbd680c63c15c$var$observedElements.delete(elementToObserve);
  32. if ($0f3bbd680c63c15c$var$observedElements.size === 0) // stop the internal loop once no elements are observed anymore
  33. cancelAnimationFrame($0f3bbd680c63c15c$var$rafId);
  34. }
  35. };
  36. } // ========================================================================
  37. // module internals
  38. let $0f3bbd680c63c15c$var$rafId;
  39. const $0f3bbd680c63c15c$var$observedElements = new Map();
  40. function $0f3bbd680c63c15c$var$runLoop() {
  41. const changedRectsData = []; // process all DOM reads first (getBoundingClientRect)
  42. $0f3bbd680c63c15c$var$observedElements.forEach((data, element)=>{
  43. const newRect = element.getBoundingClientRect(); // gather all the data for elements whose rects have changed
  44. if (!$0f3bbd680c63c15c$var$rectEquals(data.rect, newRect)) {
  45. data.rect = newRect;
  46. changedRectsData.push(data);
  47. }
  48. }); // group DOM writes here after the DOM reads (getBoundingClientRect)
  49. // as DOM writes will most likely happen with the callbacks
  50. changedRectsData.forEach((data)=>{
  51. data.callbacks.forEach((callback)=>callback(data.rect)
  52. );
  53. });
  54. $0f3bbd680c63c15c$var$rafId = requestAnimationFrame($0f3bbd680c63c15c$var$runLoop);
  55. } // ========================================================================
  56. /**
  57. * Returns whether 2 rects are equal in values
  58. */ function $0f3bbd680c63c15c$var$rectEquals(rect1, rect2) {
  59. return rect1.width === rect2.width && rect1.height === rect2.height && rect1.top === rect2.top && rect1.right === rect2.right && rect1.bottom === rect2.bottom && rect1.left === rect2.left;
  60. }
  61. export {$0f3bbd680c63c15c$export$5a50ff2cde8c3802 as observeElementRect};
  62. //# sourceMappingURL=index.mjs.map