ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Following Along Links
    Web/JS30 2020. 11. 29. 20:57
    반응형

    최근에 뭔가 낭비되는 시간이 많아졌다.

    교육 준비하면서 코딩하는 것도 있고, 학교 과제로 코딩을 하는 것도 있는데

    둘 다 마음대로 되지 않는지라, 코딩은 하고싶은데 에러가 해결되지 않아

    해결책을 찾아 헤매는 시간이 많아진다거나 하는 식으로 버려지는 시간이 길어지고 있다.

     

    물론 에러를 해결하기 위해 검색을 하고 해결책을 찾아가는 과정은 낭비라고 할 순 없겠지만

    아무리 검색을 해도 뭐가 원인인지 모르겠고, 마땅한 해결책이 나오지 않는 지금같은 경우는

    낭비라고 부를 수 있을만큼 많은 시간이 할애되는 게 문제다.

     

    그래서, 뭔가 결과물을 하나 만들어서 마음의 위로를 얻고자

    정신차리고 틈틈이 Javascript 30 같은 것들을 좀 해야겠다.


    이번에는 링크 태그에 마우스를 올릴 때마다 하이라이트가 씌워지도록 할 건데,

    한 링크에서 다른 링크로 하이라이트가 이동할 때 자연스럽게 이동하도록 효과를 구현할 것이다.

    언뜻 봐도 알 수 있듯, 하나의 하이라이트가 위치를 바꿔가며 만들어지는 효과이기 때문에

    일단 'highlight'라는 클래스를 가진 span 태그를 하나 만들어놓고

    마우스가 위치한 a 태그를 따라 width, height,

    그리고 transform: translate(x, y)를 변경하는 식으로 구현할 예정이다.

    const triggers = document.querySelectorAll('a');
    const highlight = document.createElement('span');
    highlight.classList.add('highlight');
    document.body.append(highlight);

    참고로, highlight 클래스의 css 효과는 다음과 같다.

    .highlight {
        transition: all 0.2s;
        border-bottom: 2px solid white;
        position: absolute;
        top: 0;
        background: white;
        left: 0;
        z-index: -1;
        border-radius: 20px;
        display: block;
        box-shadow: 0 0 10px rgba(0,0,0,0.2);
    }

    일단 이 효과는 링크 태그에 마우스를 올려놓을 때 발현되므로

    각 링크 태그마다 마우스가 올라오는지를 감시하는 이벤트 리스너를 달아준다.

    triggers.forEach(a => a.addEventListener('mouseenter', highlightLink));

    이제, highlightLink 함수를 구현해 줄 차례이다.

    여기서, 링크 태그에 포함된 각 단어의 크기에 맞는 하이라이트를 위해서는

    각 링크 태그가 가지는 width, height, 그리고 x, y 크기 등을 알아내야한다.

    이를 가장 간단하게 알아낼 수 있는 방법은 바로 'getBoundingClientRect' 메서드를 이용하는 것이다.

    function highlightLink() {
        const linkCoords = this.getBoundingClientRect();
        console.log(linkCoords);
    }

    getBoundingClientRect 메서드를 이용하면, 해당 element의 width, height 등 크기 뿐만 아니라

    left, right, top, bottom, x, y 등의 위치까지도 알 수가 있다.

     

    좀 더 자세한 내용은 여기에서.

     

    getBoundingClientRect를 이용해서 각 링크 태그의 width, height, top, left 값을 알 수 있으므로

    이제 이를 이용해서 CSS 값을 변경해주기만 하면 된다.

    function highlightLink() {
        const linkCoords = this.getBoundingClientRect();
    
        highlight.style.width = `${linkCoords.width}px`;
        highlight.style.height = `${linkCoords.height}px`;
        highlight.style.transform = `translate(${linkCoords.left}px, ${linkCoords.top}px)`;
    }

    근데, 위와 같이 코드를 입력하고 실행시켜보면 한 가지 이상한 점을 발견할 수가 있다.

    처음에 링크 태그에 마우스를 갖다대면 아무 문제 없이 효과가 잘 나타나지만,

    페이지를 아래로 스크롤하고 마우스를 갖다대면

    조금씩 위치가 엇나가기 때문이다.

    이는 transform과 getBoundingClientRect의 차이에서 오는 문제이다.

    transform 속성은 현재 화면에 들어오는 브라우저 내부를 기준으로 하지만

    getBoundingClientRect의 top 속성은 페이지 전체의 최상단부터의 길이를 측정한다.

    그래서 스크롤을 한 높이만큼 두 속성값이 차이가 생기게 되는 것.

     

    이를 반영하여, 다음과 같이 코드를 고쳐주면 문제가 해결된다.

    function highlightLink() {
          const linkCoords = this.getBoundingClientRect();
    
          highlight.style.width = `${linkCoords.width}px`;
          highlight.style.height = `${linkCoords.height}px`;
          highlight.style.transform = `translate(${linkCoords.left + window.scrollX}px, 
                                                 ${linkCoords.top + window.scrollY}px)`;
        }

    linkCoords.top에다가 스크롤을 한 만큼의 높이인 window.scrollY를 더해주면

    우리가 원하는 곳에 하이라이트가 정확히 씌워지는 모습을 볼 수 있을 것이다.

     

    혹시나 x축 방향으로도 스크롤이 생기는 것을 대비해, linkCoords.left에도 window.scrollX를 더해줬다.

     

    전체 자바스크립트 코드

    <script>
        const triggers = document.querySelectorAll('a');
        const highlight = document.createElement('span');
        highlight.classList.add('highlight');
        document.body.append(highlight);
    
        function highlightLink() {
            const linkCoords = this.getBoundingClientRect();
    
            highlight.style.width = `${linkCoords.width}px`;
            highlight.style.height = `${linkCoords.height}px`;
            highlight.style.transform = `translate(${linkCoords.left + window.scrollX}px, 
                                                   ${linkCoords.top + window.scrollY}px)`;
        }
    
        triggers.forEach(a => a.addEventListener('mouseenter', highlightLink));
    </script>

     

    반응형

    'Web > JS30' 카테고리의 다른 글

    Sticky Nav 🩹  (0) 2020.12.23
    📢 Speech Synthesis 🔊  (0) 2020.12.23
    🎤Native Speech Recognition📢  (0) 2020.11.23
    ⌚Tally String Times with Reduce⏱  (0) 2020.11.20
    📊 Sort Without Articles 🎢  (0) 2020.11.19

    댓글

Designed by Tistory.