Angular ScrollService Scroll

agnusdei·2023년 7월 5일
0
post-custom-banner
import { ElementRef, Injectable, QueryList } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class ScrollService {
  subject$ = new Subject(); // 스크롤 이벤트를 전달하기 위한 Subject 객체

  select(index: number) {
    this.subject$.next(index); // 주어진 인덱스를 Subject에 전달하여 구독자들에게 알림
  }

  scrollTo(found: ElementRef<HTMLElement>) {
    if (found) {
      const layout = document.querySelector('#layout'); // id가 'layout'인 요소를 가져옴

      // 스크롤 위치 계산
      const top =
        found.nativeElement.getBoundingClientRect().top +
        layout.scrollTop -
        layout.clientTop -
        70;

      if (layout) {
        layout.scrollTo({
          top: top,
          behavior: 'smooth', // 부드러운 스크롤 동작 설정
        });
      }
    }
  }

  observe(sections: QueryList<ElementRef<HTMLElement>>) {
    this.subject$.subscribe((index: number) => {
      const found = sections.find((section, i) => i === index); // 주어진 인덱스에 해당하는 요소를 찾음
      this.scrollTo(found); // 해당 요소로 스크롤 이동
    });
  }
}
  1. 스크롤 서비스
<section #sections></section>
<section #sections></section>
<section #sections></section>
<section #sections></section>
<section #sections></section>
  1. 템플릿 예시
 @ViewChildren('sections') sections!: QueryList<ElementRef<HTMLElement>>;
 
 
 ngAfterViewInit(): void { // 템플릿이 전부 그려진 후
    this.scrollService.observe(this.sections); // 섹션들 HTML 객체 타입으로 전달
  }

3.. 컴포넌트 내부

QueryList는 Angular에서 제공하는 컬렉션 타입으로, 여러 개의 DOM 요소에 대한 참조를 저장하고 관리하는 기능을 제공합니다. QueryList는 주로 @ViewChildren 데코레이터와 함께 사용되어 템플릿에서 선택자를 사용하여 여러 DOM 요소를 참조하는 데 유용합니다.

  1. 요소 추가 및 제거: QueryList는 동적으로 요소를 추가하거나 제거할 수 있는 기능을 제공합니다. 즉, DOM에 새로운 요소가 추가되거나 삭제되면 QueryList도 자동으로 업데이트됩니다.

  2. 요소 순회: QueryListforEach() 메서드를 통해 내부에 저장된 요소들을 순회할 수 있습니다. 이를 통해 각 요소에 접근하고 작업을 수행할 수 있습니다.

  3. 변경 감지: QueryList는 내부 요소의 상태 변경을 감지할 수 있습니다. 예를 들어, 요소의 속성이 변경되면 QueryList는 이를 감지하여 자동으로 업데이트됩니다.

  4. 이벤트 감지: QueryList는 내부 요소에서 발생하는 이벤트를 감지할 수 있습니다. 이를 통해 특정 이벤트에 대한 처리를 수행하거나 상호작용할 수 있습니다.

따라서, 주어진 코드에서 sections 변수는 QueryList<ElementRef<HTMLElement>> 타입으로 선언되어 여러 DOM 요소의 참조를 저장하고 관리합니다. 이를 통해 템플릿에서 선택자를 사용하여 해당 요소들에 접근하고 조작할 수 있습니다. 변경된 요소에 대한 업데이트 및 이벤트 감지도 자동으로 처리됩니다.

<div
      class="flex flex-col justify-start gap-2.5 cursor-pointer p-2 bg-gray-50"
      *ngFor="let child of menu.children; index as i"
    >
      <div (click)="_scrollTo(i)">
        <div
          class="font-semibold text-sm text-gray-800 hover:bg-gray-100 py-2 rounded-xl px-10 w-full"
        >
          <p>{{ child.name }}</p>
        </div>
      </div>
    </div>
  1. 컴포넌트의 컴포넌트 (click) 이벤트에 달아서 활용
 _scrollTo(index: number) {
    this.scrollService.select(index);
  }
post-custom-banner

0개의 댓글