[JavaScript] 22. Following Highlight
💡 메뉴바에서 내가 선택한 메뉴를 표시할 때
`hover`나 `classList.add` & `classList.remove`를 통해 해당 요소 자체에 CSS 값을 적용하는 방식이 아닌,
`getBoundingClientRect()`메서드를 통해 해당 요소의 위치와 크기를 구한 후, 따로 만들어놓은 배경이 이를 따라다니도록 하는 방식이다.
로직
- 미리 HTML 내에 배경 역할의
<span>
태그 생성 (createElement
,append
) - 모든
<a>
태그에 마우스 이벤트로 함수 호출하도록 설정 (mouseenter
) - 이벤트가 발생한
<a>
태그의 뷰포트 기준 위치를 구함 (getBoundingClientRect()
) - 스크롤로 인한 위치 변화값을 자동 계산하도록 수정 (
window.scrollX
,window.scrollY
) - 해당 위치값을 그대로
<span>
태그에 적용하여 해당<a>
태그의 배경 역할을 하도록 함
코딩 과정
1. 배경 역할을 하는 <span>
태그 생성
const highlight = document.createElement("span");
//배경 역할을 할 수 있도록 CSS가 적용돼있는 class를 추가
highlight.classList.add("highlight");
//이벤트가 발생하기전에 우선 body안에 넣어둠
document.body.append(highlight);
createElement()
const highlight = document.createElement("span");
HTML 문서에서 document.createElement() 메서드는 지정한 tagName의 HTML 요소를 생성한다.
💡 이는 단순히 요소를 생성했을 뿐, HTML document 내의 무엇인가에 append 하기전에는 구현되지 않는다.
append()
document.body.append(highlight);
Element.append() 메서드는 부모 요소에 자식 요소를 추가한다.
이때 문자열 또한 추가 가능하며 여러 개의 자식 요소를 한번에 추가할 수도 있다.
💡 기본 width값과 height값을 설정 안해줬으므로 마우스 이벤트가 일어나기전에는 화면에 표시 ❌
2. 모든 <a>
태그에 이벤트리스너 설정
const triggers = document.querySelectorAll("a");
triggers.forEach((a) => a.addEventListener("mouseenter", highlightLink));
mouseenter와 mouseover 비교
둘 다 공통적으로 해당 요소에 마우스가 올라가는 것을 감지한다.
둘의 차이점은
mouseenter : 자식 요소의 영역에 들어가면 감지 x
⇒ 해당 요소에서 자식 요소의 영역으로 마우스가 움직여도 따로 이벤트 발생하지 않음
mouseover : 자식 요소의 영역까지 감지 o
⇒ 마우스가 해당 요소와 자식 요소의 영역 경계를 넘나들때마다 이벤트 발생함
3. 이벤트가 발생한 <a>
태그의 뷰포트 기준 위치 구하기
function highlightLink() {
const linkCoords = this.getBoundingClientRect();
//구한 뷰포트 기준 위치값을 'highlight' span에 적용
highlight.style.width = `${linkCoords.width}px`;
highlight.style.height = `${linkCoords.height}px`;
highlight.style.transform = `translate(${linkCoords.left}px, ${linkCoords.top}px)`;
}
getBoundingClientRect()
const linkCoords = this.getBoundingClientRect();
DOMRect를 뷰포트 기준으로 반환해주는 메서드이다.
❓ DOMRect 란?
요소의 각종 좌표값이 들어있는 객체이며
요소를 감싸는 사각형 형태로 사이즈와 위치 정보를 나타낸다.
이 사각형은 요소의 contexts, padding, border를 포함한다.
4. 스크롤로 인한 위치 변화 계산
getBoundingClientRect()를 통해 구한 값은 뷰포트를 기준으로 하는 요소의 상대좌표
⇒ 화면을 스크롤 할 경우 요소의 위치값이 달라진다.
'highlight' span의 경우 뷰포트 기준으로 이동하는게 아니라 스크롤을 포함한 맨 위, 맨 왼쪽 부분을 기준으로 이동
⇒ 스크롤 한 상태에서 이동할 경우 스크롤 한 만큼 요소와 위치가 어긋나게 된다.
따라서!
뷰포트 기준 위치값에 window.scrollX, window.scrollY로 스크롤한 X, Y 값을 가져와서 더해주어야 정확한 요소의 위치로 'highlight' span이 이동한다.
function highlightLink() {
const linkCoords = this.getBoundingClientRect();
const coords = {
width: linkCoords.width,
height: linkCoords.height,
//뷰포트 값에 스크롤된 길이를 더해준다.
top: linkCoords.top + window.scrollY,
left: linkCoords.left + window.scrollX,
};
highlight.style.width = `${coords.width}px`;
highlight.style.height = `${coords.height}px`;
highlight.style.transform = `translate(${coords.left}px, ${coords.top}px)`;
}
최종 완성 코드
const triggers = document.querySelectorAll("a");
const highlight = document.createElement("span");
highlight.classList.add("highlight");
document.body.append(highlight);
function highlightLink() {
const linkCoords = this.getBoundingClientRect();
const coords = {
width: linkCoords.width,
height: linkCoords.height,
top: linkCoords.top + window.scrollY,
left: linkCoords.left + window.scrollX,
};
highlight.style.width = `${coords.width}px`;
highlight.style.height = `${coords.height}px`;
highlight.style.transform = `translate(${coords.left}px, ${coords.top}px)`;
}
triggers.forEach((a) => a.addEventListener("mouseenter", highlightLink));
Author And Source
이 문제에 관하여([JavaScript] 22. Following Highlight), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@amgona94/22.-Following-Highlight저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)