본문 바로가기
javascript/사이드 프로젝트

ResizeObserver 과 svg Element는 같이 동작하지 않는다.

by 윤-찬미 2021. 3. 12.

👀 서론

요즘 D3에빠져 데이터 시각화에 관심이 많은 한사람 입니다.

(리액트에서 D3를 이용하려다 보니 둘의 Dom control이 달라서 어떻게 해야 잘 쓸 수 있는지 고민이 많습니다..ㅋㅋ)

 

D3랑관련 있는 이야기는 아니고, 그래프 그리다가 돔 크기에 따라 그래프가 유연하게 그려졌으면 좋겠어서

ResizeObserver 을 이용해서 하고 있습니다.

ResizeObserver에 대한 설명은 아래 MDN참고 하세요!

developer.mozilla.org/en-US/docs/Web/API/ResizeObserver

 

ResizeObserver - Web APIs | MDN

ResizeObserver The ResizeObserver interface reports changes to the dimensions of an Element's content or border box, or the bounding box of an SVGElement. Note: The content box is the box in which content can be placed, meaning the border box minus the pad

developer.mozilla.org

👀 ResizeObserver를 이용한 custom hooks

ResizeObserver 을 해서 크기 요소를 반환해주는 custom hooks를 이용하고 있습니다. 아래와 같이요!

import { useEffect, useState } from "react";

const useResizeObserverHooks = (ref) => {
  const [dimensions, setDimensions] = useState(null);
  useEffect(() => {
    const observerTarget = ref.current;
    console.log(observerTarget);
    const resizeObserver = new ResizeObserver((entries) => {
      console.log(entries);
      entries.forEach((entry) => {
        setDimensions(entry.contentRect);
      });
    });
    resizeObserver.observe(observerTarget);
    return () => {
      resizeObserver.unobserve(observerTarget);
    }
  }, [ref, dimensions]);
  return dimensions;
}

export default useResizeObserverHooks;

 

👀 ResizeObserver이 동작을 안한다

그런데, ref에 svg Element를 넘겨주니 ResizeObserver가 동작을 안하더라구요.

const svgRef = useRef();

const dimensions = useResizeObserverHooks(svgRef);
 <SvgCondition ref={svgRef}>
   <g className="x-axis" />
   <g className="y-axis" />
 </SvgCondition>

 

👀 원인이 무엇인가

이것때문에 원인 찾느라 한 이틀 헤매인 것 같습니다.

처음에는 svg Element가 원인인지 몰랐고, 제 코드상의 문제 인가 싶었거든요.

 

결론은 svg Element랑 ResizeObserver는 함께 사용할 수 없었고, 그 이유를 찾다보니 아래와 같이 나오더라구요.

 

" As a developer, I expect SVG and HTML Elements to behave similarly, but according to spec they are different. SVGElements do not have a contentBox, which is what we are observing. "

"From what i can tell from reading the spec, SVG's aren't currently observable, though the intent is there for them to be. this is due to a technical reason, as they use a bounding box, rather than content box. thus ResizeObserver is not able to observe the changes and fire events. This is a current limitation they are working on. I do not know if there is any available workaround or not."

 

위의 내용을 요약하면,

SVG는 현재 관찰 가능한 대상이 아닙니다. SVG는 content box 가 아닌 bounding box를 사용하기 때문 입니다.

따라서 ResizeObserver를 사용하여, 변경 사항을 관찰하고 이벤트를 발생시킬 수 없습니다. 

 

포인트는 SVG는 content box 가 아닌 bounding box를 사용 하기 때문 입니다.

 

The second parameter, options, is optional. Currently, the only option available is box which determines the box model we want observe changes to. Possible values are content-box (default), border-box and device-pixel-content-box(which is chrome only). You can only observe one box per observer, so you will need to use multiple ResizeObservers if you want to observe multiple boxes for the same element.

 

target이 content-box여야 동작을 하는데 svg는 그렇지 않기 때문입니다..

 

 

 

 

 

 

혹시나 저와 같은 문제를 겪으신 분이 계신다면 도움이 되길 바라며,,,,

 

그래서 div로 랩핑시켜 사용했더니 정상 작동 합니다.