Wesbos - 따라다니는 하이라이트


완성본 예시

추후에 드롭다운 메뉴 등에 활용할 수 있을 것 같은 기능이다.
원래 나였으면 CSS값을 add하고 remove하는 방식을 썼을 것 같은데, 이번 챕터에선 하이라이터가 마우스가 올라간 객체의 위치값을 활용해서 하이라이팅한다.


로직

  1. HTML, CSS값 선언 및 할당 (const)
  2. 스크롤 했을 때를 가정하여 위치값 설정 (window.scrollY)
  3. 이벤트리스너와 함수 생성 (mouseenter)
  4. 마우스가 올라간 객체의 위치값 활용 getBoundingClientRect()

const 선언부터…

💡 태그에 하이라이팅을 할 것이므로 ⇒ a태그를 선언 + 하이라이팅 요소(span)를 생성해주기

주의‼️

원래는 CSS값을 add하고 remove하는 방식이지만,
여기선 하이라이트 요소를 만들어놓고 → 요놈을 움직이고 크기를 조절하며 하이라이팅 함

1
2
3
4
5
6
7
const triggers = document.querySelectorAll('a');
// 하이라이트는 <span>을 사용할 것
const highlight = document.createElement('span');
// 미리 설정해둔 CSS값을 "하이라이트 span에" 적용
highlight.classList.add('highlight');
// 일단 그냥 띄워두기
document.body.append(highlight);

이벤트리스너와 함수 생성

💡 mouseenter을 활용

mouseenter vs mouseover

mouseover : 자식요소에까지 이벤트가 할당됨

1
2
3
4
5
function highlightLink() {
console.log(this);
}

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

찍어보기


위치값을 활용한 하이라이트

💡 여기서부턴 처음 사용해보는 메서드를 활용해야한다.

Element.getBoundingClientRect()

뷰포트를 기준으로 한 상대적 엘리먼트의 위치와 사이즈를 포함하는 DOMRect를 리턴해준다.

콘솔창 확인

highlight의 너비와 위치가 동적으로 변할 수 있도록 설정

1
2
3
4
5
6
7
8
function highlightLink() {
const linkCoords = this.getBoundingClientRect();
console.log(linkCoords);
highlight.style.width = `${linkCoords.width}px`;
highlight.style.height = `${linkCoords.height}px`;
highlight.style.left = `${linkCoords.left}px`;
highlight.style.top = `${linkCoords.top}px`;
}

스크롤값을 반영

하지만… 스크롤을 내리면 아래와 같이 스크롤을 내리기 전 위치값으로 이동되기 때문에 highlight의 위치값에 스크롤 이동에 따른 변화값을 추가해줘야된다.

1
2
3
4
5
6
7
8
9
10
function highlightLink() {
const linkCoords = this.getBoundingClientRect();
highlight.style.width = `${linkCoords.width}px`;
highlight.style.height = `${linkCoords.height}px`;
// top, left 값에 각각 스크롤한 만큼의 값을 더해줌!
const scrollY = linkCoords.top + window.scrollY;
const scrollX = linkCoords.left + window.scrollX;
highlight.style.left = `${scrollX}px`;
highlight.style.top = `${scrollY}px`;
}

최종 완성 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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`;
const scrollY = linkCoords.top + window.scrollY;
const scrollX = linkCoords.left + window.scrollX;
highlight.style.left = `${scrollX}px`;
highlight.style.top = `${scrollY}px`;
highlight.style.opacity = 1;
}

//마우스가 나가있을 때 사라지게 할 수 있도록 opacity값을 변경하는 함수도 추가했다.

function deHighlight() {
highlight.style.opacity = 0;
}

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

Author

Hoonjoo

Posted on

2022-01-05

Updated on

2022-02-07

Licensed under

Comments