지정영역에서 이벤트 발생 후 재실행

J-silver·2024년 12월 17일

gsap를 이용해서 스크롤시 내가 원하는 영역에서 이벤트가 발생하고 해당영역을 벗어나면 다시 이벤트가 나타나는걸 작성했는데 원하는대로 안됨ㅠ

내가 처음 작성한것

1. gsap를 이용

ScrollTrigger.create({
  trigger: ".project-area", // .project-area에 트리거 설정
  start: "top top", // .project-area의 상단이 뷰포트 상단에 닿으면 시작
  end: "bottom top", // .project-area의 하단이 뷰포트 상단에 닿으면 종료
  toggleActions: "play none none reverse", // 실행: play, 복귀: reverse
  onEnter: () => {
    gsap.to("#header", { opacity: 0, y: -20, duration: 0.2 }); // 헤더 숨김
  },
  onLeaveBack: () => {
    gsap.to("#header", { opacity: 1, y: 0, duration: 0.2 }); // 헤더 복귀
  }
});

🤔 문제점project-area를 못잡는다

내가 생각한 해결법
1. 부모한데 300vh를 줘서 스크롤할 높이값을 준다. -> 실패
2. end를 100%를 줘서 전체 높이값을 잡도록한다 -> 여전히 못잡음

👀 3. 서치를 통해 찾은 다른 해결법

onEnter: () => {
    gsap.to("#header", { opacity: 0, y: -20, duration: 0.2 }); // 헤더 숨김
  },
  onLeave: () => {
    gsap.to("#header", { opacity: 1, y: 0, duration: 0.2 }); // 헤더 복귀 (project-area 벗어날 때)
  },
  onEnterBack: () => {
    gsap.to("#header", { opacity: 0, y: -20, duration: 0.2 }); // 다시 project-area로 진입 시 숨김
  },
  onLeaveBack: () => {
    gsap.to("#header", { opacity: 1, y: 0, duration: 0.2 }); // 위로 벗어나면 복귀
  }

-> 여전히 못잡음

👀 4. invalidateOnRefresh 트리거 재계산 -> 안먹음x

5. scroll이벤트를 이용해서 잡기

let lastScroll = 0;

$(window).scroll(function () {
  const currScroll = $(this).scrollTop(); // 현재 스크롤 위치
  const projectAreaOffset = $(".project-area").offset().top; // .project-area의 상단 위치
  const projectAreaHeight = $(".project-area").outerHeight(); // .project-area의 높이
  const projectAreaEnd = projectAreaOffset + projectAreaHeight; // .project-area의 하단 위치

  // 스크롤이 .project-area에 있을 때만 동작
  if (currScroll >= projectAreaOffset && currScroll <= projectAreaEnd) {
    if (currScroll > lastScroll) {
      // 아래로 스크롤
      gsap.to(".header", { opacity: 0, duration: 0.1 });
    } else {
      // 위로 스크롤
      gsap.to(".header", { opacity: 1, duration: 0.1 });
    }
  } else {
    // .project-area를 벗어나면 헤더를 항상 보이게 설정
    gsap.to(".header", { opacity: 1, duration: 0.1 });
  }

  lastScroll = currScroll; // 마지막 스크롤 위치 갱신
});

해결!
하지만 새로운 문제 project-area를 벗어나고 다시 스크롤을 위로 올려서 영역에 들어가면
그대로 존재😢

⭕찐해결법

let isInProjectArea = false;를 이요해서 영역에 들어갔는지 여부를 추적하면 된다!!!

  if (curr >= projectAreaOffset && curr <= projectAreaEnd) {
    if (!isInProjectArea) {
      // .project-area에 처음 진입한 경우
      $(".header").fadeOut();
      isInProjectArea = true; // .project-area 내부로 상태 갱신
    }
  } else {
    // .project-area를 벗어나면 헤더를 다시 표시
    if (isInProjectArea) {
      $(".header").fadeIn();
      isInProjectArea = false; // .project-area 외부로 상태 갱신
    }
  }

두 번 선언하는 이유는 퍼포먼스 최적화와 정확한 동작 보장 때문

1. $(window).scroll 내부에서 선언
스크롤 이벤트 내부에서 위치와 크기를 다시 계산하는 이유는 $(".project-area")의 위치나 크기가 스크롤 중에 동적으로 변경될 가능성이 있기 때문입니다.

2. 전역 변수 및 resize 이벤트
.project-area의 위치와 크기가 고정된 경우. 반복적으로 계산하지 않고 성능을 최적화.

🤔언제 두 방식을 동시에 사용하는가?

1. 전역 변수 + resize 이벤트
상황: .project-area의 위치와 크기가 대부분 고정되어 있고, 브라우저 창 크기 변경 시만 업데이트가 필요할 때.
장점: 스크롤 이벤트를 가볍게 만들고, 성능을 최적화.

2. 스크롤 이벤트 내부에서 계산
상황: .project-area의 위치나 크기가 스크롤 도중 동적으로 변경될 가능성이 있을 때.
장점: 위치와 크기의 정확성을 보장.

3. 둘을 함께 사용하는 이유
기본적으로 전역 변수와 resize 이벤트를 사용해 성능을 최적화.
하지만 특정 상황에서는 스크롤 이벤트 내에서도 실시간으로 값을 재계산해야 동작의 정확성을 보장.

profile
달리는 거북이

0개의 댓글