스크롤에 반응하는 목차 하이라이트 만들기

예리에르·2022년 8월 26일
5

React

목록 보기
14/17
post-thumbnail

계기

  • 사내에서 사용하는 시스템으로 마크다운 형식으로 문서를 작성하고 공유하는 서비스를 만들었다. 스터디 내용도 정리하고 개발관련 지식도 공유할수 있는 서비스이다.
  • 기존에 만들어진 마크다운은 <a/> 태그의 href 기능을 사용해 스크롤을 목차에 맞게 이동하는 기능만 들어가 있었다.

문제점

  • 여기서 문제점은 제목을 id 값으로 받고 이동하다보니 만약에 한 문서의 같은 id가 있게된다면 원하는 목차로 이동할 수가 없었다.
<a href="#List(리스트)">List(리스트)</a>

...

<div id="List(리스트)" >List(리스트)</div>
  • 현재 시스템은 스크롤에 따라 목차가 하이라이트 되는 기능은 아예 없기 때문에 개선과 더불어 새 기능을 덧붙여야 한다.

1. id별 unique 속성 추가해주기

문서의 제목만을 id값으로 가지는 것이 아니라 구분 할 수 있는 unique한 값이 있으면 좋겠다고 생각했다.

여기서 독특한 값을 생각해보면 해당 목차가 있는 줄의 위치는 무조건 다르다는 특성이 있다.

<a href="#List(리스트)-62">List(리스트)</a>

...

<div id="List(리스트)-62" >List(리스트)</div>
  • 위의 id와 비교해보면 62번째 줄의 목차로 이동하는 구나 라는 좀더 구체적인 목차를 특정할 수 있게되었다.

2. 스크롤 이벤트 감지후 목차 하이라이트

스크롤 이벤트 등록하기

 componentDidMount() {
        window.addEventListener('scroll',this.handleScroll);
    }
componentWillUnmount() {
        window.removeEventListener('scroll',this.handleScroll);
    }

...

 @computed
    private get isFocusHead() {
        return this.distance< 70 && this.distance>0;
    }

@action
    private handleScroll = () => {
        const {children = [],node={},level = -1} = this.props;
        const line = node.position.start.line;

        if (level>0 && level <4) {
            const target = document.getElementsByClassName(`${this.props.children.join("")+ "-" + this.props.node.position.start.line}`)[0];
            const clientRect = target.getBoundingClientRect();
            const relativeTop = clientRect.top;
            this.distance = relativeTop;
            if (this.isFocusHead) {
                this.inject.resourceStore.setFocusHeadClassName(children.join("") + "-" + line);
            }
        }

    }
  • 스크롤이 이벤트가 발생하면 실행할 handleScroll 함수를 만든다.

  • level은 markdown에서 h1 h2 ... 를 의미한다. 원하는 header를 가지기 위해 조건문을 추가했다.

  • 관찰하고자 하는 target 을 가져온후 뷰포트 기준에서 상대적인 위치를 가져온다.

  • 자신이 원하는 범위에 target이 들어오다면 target의 이름을 store에 올려준다.

    	스토어에 올린 이유는 마크다운을 보여주는 컴포넌트와 목차를 보여주는 컴포넌트가 한 부모에 속해있지 않기 때문에 상태관리 store에 올려 관찰하였다.


마지막으로 목차에서 store에 있는 클래스이름과 목차 클래스이름과 같을때 css 작업을 더해주면 스크롤에 따른 목차 하이라이트가 완성되었다.

profile
비전공 프론트엔드 개발자의 개발일기😈 ✍️

0개의 댓글