In a clojurescript project, I have an svg element represented as hiccup and I want to measure it’s exact size. The way I’m doing it is to render the element using reagent.dom/render and then measure the element using getBBox (https://developer.mozilla.org/en-US/docs/Web/API/SVGGraphicsElement/getBBox). As soon as I’ve measured its size I remove the element from the dom because I don’t need it, I just want to know what its dimensions would be when rendered
Here’s my code. It seems to work fine, but what I’m wondering is, am I creating a race condition where .getBBox could be called before reagent.dom/render has finished rendering the SVG? If so, how can I avoid this race condition?
(defn measure-svg-element
"Given an svg element has hiccup, measure its size precisely
by rendering it and using getBBox. Returns a map with keys
x, y, width, height"
[element-hiccup]
(let [el-id (str "el-" (random-uuid))
div-id (str "div-" (random-uuid))
svg [:svg
{:xmlns "http://www.w3.org/2000/svg"
:id el-id}
element-hiccup]
body (-> js/document (.querySelector "body"))
div (-> js/document (.createElement "div"))]
(-> div (.setAttribute "id" div-id))
(-> body (.append div))
(rdom/render svg
(-> js/document (.getElementById div-id)))
(let [el (-> js/document (.getElementById el-id))
bbox (.getBBox el)
dimensions {:width (.-width bbox)
:height (.-height bbox)
:x (.-x bbox)
:y (.-y bbox)}]
(rdom/unmount-component-at-node (-> js/document (.getElementById div-id)))
(-> div (.remove))
dimensions)))