Interactive/GSAP

스크롤 트리거 - 플러그인 | GSAP

AGAL 2021. 4. 5. 18:06
반응형

 

ScrollTrigger는 최소한의 코드로 놀라운 스크롤 기반 애니메이션을 만듭니다 . 또는 애니메이션과 무관하더라도 스크롤과 관련된 모든 것을 트리거합니다.

 

가장 일반적인 ScrollTrigger 실수에 대해서도 학습하여 게임에서 앞서 나가세요.

 

 

주요 기능

  • 특정 요소에 애니메이션을 연결하여 해당 요소가 뷰포트에 있을 때만 재생되도롭 합니다. 이렇게 하면 성능이 향상되고 아름다운 애니메이션을 실제로 볼 수 있습니다.
  • ScrollTrigger는 정의된 영역에 들어가거나 나갈 때 애니메이션에 대한 작업(재생, 일시 중지, 다시 시작, 되감기, 완료, 재설정)을 수행하거나 스크러버(scrub: true)처럼 작동하도록 스크롤바에 직접 연결할 수 있습니다.
  • 애니메이션과 스크롤바 사이의 연결을 부드럽게하여 "추적"하는 데 일정 시간이 걸리도록합니다. scrub: 1은 따라 잡는 데 1 초가 걸립니다.
  • 속도에 따라 애니메이션의 특정 지점을 스냅합니다. 사실, 스크롤링의 getVelocity()는 언제든지 가능합니다. 타임라인에서 가장 가까운 레이블 또는 어레이의 진행률 값에 스냅하거나 사용자 지정 함수 기반 로직을 실행하여 스냅합니다.
  • 스크롤 트리거를 GSAP 애니메이션에(타임라인 포함) 직접 포함하거나 독립 실행형 인스턴스를 만들고 풍부한 콜백 시스템을 활용하여 원하는 작업을 수행 할 수 있습니다.
  • 고급 고정 기능은 특정 스크롤 위치 사이에서 요소를 잠글 수 있습니다. 그에 따라 다른 요소를 아래로 밀어 내기 위해 패딩이 자동으로 추가되므로 요소가 고정 해제되면 따라 잡습니다 (pinSpacing : false로 비활성화). 동일한 요소를 다른 지점에 여러 번 고정 할 수도 있습니다.
  • 스크롤 위치를 정의하는 놀라운 유연성 - "이 요소의 중심이 뷰포트의 중앙에 닿으면 시작하고 다른 요소의 하단이 뷰포트의 하단에 닿으면 종료"와 같이 키워드 (top, center, bottom, left), 백분율, 픽셀 또는 "+ = 300px"와 같은 상대 값을 사용합니다. 구문에 익숙해지면 매우 직관적입니다.
  • 수직 또는 수평 스크롤을 수용합니다.
  • onEnter, onLeave, onEnterBack, onLeaveBack, onToggle, onUpdate, onScrubComplete 및 onRefresh를 포함한 풍부한 콜백 시스템.
  • 창 크기가 조정되면 자동으로 위치를 다시 계산합니다.
  • 개발 중에 시각적 마커를 활성화하여 시작 / 종료 / 트리거 지점의 정확한 위치를 확인합니다. markers: {startColor : "green", endColor : "red", fontSize : "12px"}와 같은 사용자 지정 옵션이 풍부합니다.
  • CSS 클래스를 전환합니다. 예를 들어 toggleClass : "active"는 ScrollTrigger가 활성화 된 동안 트리거 요소에 "active"클래스를 추가합니다. 다른 요소에도 영향을 미칠 수 있습니다.
  • 반응형 - matchMedia() 메서드를 사용하여 표준 미디어 쿼리를 사용하여 다양한 화면 크기에 대해 다른 설정을 만듭니다.
  • 커스텀 컨테이너 - 뷰포트를 사용할 필요가 없습니다. 대신 <div>와 같은 사용자 지정 스크롤러를 정의하십시오.
  • 최대 성능을 위해 고도로 최적화 됨 - 스크롤 이벤트가 디 바운스되고 업데이트가 GSAP와 동기화 되며, 화면 새로 고침, 크기 조정 재계산 등이 조절됩니다.
  • 스크롤 재킹이 없으므로 CSS 스크롤 스냅과 같은 기본 기술과 결합 할 수 있습니다. 스크롤 재킹을 원하는 경우 scrollerProxy() 메서드를 사용하여 타른 스크롤 라이브러리와 통합 할 수 있습니다.
  • 대략 6.5kb gzip입니다.

 

간단한 예

gsap.to(".box", {
  scrollTrigger: ".box", // ".box"가 뷰포트에 들어갈 때 애니메이션을 시작합니다(한 번).
  x: 500
});

 

고급 예

let tl = gsap.timeline({
    // 전체 타임라인에 추가할 수 있습니다!
    scrollTrigger: {
      trigger: ".container",
      pin: true,   // 활성 상태에서 트리거 요소 고정
      start: "top top", // 트리거 상단이 뷰포트 상단에 닿을 때
      end: "+=500", // 시작 부분에서 500px 까지 스크롤 한 후 종료
      scrub: 1, // 부드러운 스크러빙, 스크롤바를 "잡는"데 1초가 걸립니다.
      snap: {
        snapTo: "labels", // 타임라인에서 가장 가까운 레이블에 스냅
        duration: {min: 0.2, max: 3}, // 스냅 애니메이션은 0.2초 이상 3초 이하이어야 합니다(속도에 따라 결정됨).
        delay: 0.2, // 스냅을 수행하기 전에 마지막 스크롤 이벤트에서 0.2 초를 기다립니다.
        ease: "power1.inOut" // 스냅 애니메이션의 ease (기본적으로 "power3")
      }
    }
  });

// 애니메이션 및 레이블을 타임라인에 추가합니다.
tl.addLabel("start")
  .from(".box p", {scale: 0.3, rotation:45, autoAlpha: 0})
  .addLabel("color")
  .from(".box", {backgroundColor: "#28a92b"})
  .addLabel("spin")
  .to(".box", {rotation: 360})
  .addLabel("end");

 

독립형 / 사용자 지정 예

ScrollTrigger를 애니메이션에 직접 넣을 필요는 없습니다(가장 일반적인 사용 사례일 수도 있음). 아무거나 콜백을 이용하세요.

ScrollTrigger.create({
  trigger: "#id",
  start: "top top",
  endTrigger: "#otherID",
  end: "bottom 50%+=100px",
  onToggle: self => console.log("toggled, isActive:", self.isActive),
  onUpdate: self => {
    console.log("progress:", self.progress.toFixed(3), "direction:", self.direction, "velocity", self.getVelocity());
  }
});

 

사용 및 특수 속성

scrollTrigger는 트리거(아래 설명)의 약자로 사용하거나 다음 속성 중 하나를 사용하여 구성 객체로 사용할 수 있습니다.

GSAP 공식 문서 참조

 

ScrollTrigger는 어떻게 작동합니까? IntersectionObserver와 똑같습니까?

Scroll Trigger(스크롤 트리거)가 모든 요소를 지속적으로 감시하고 각 체크 표시의 뷰포트에서 해당 위치를 확인하는 것은 아닙니다. 우리는 성능에 집착하고 있고, 그것은 비용이 너무 많이 들 것입니다. 대신, Scroll Trigger(스크롤 트리거)는 문서 흐름에서 시작점/끝점의 위치를 파악하기 위해 사전 처리를 수행합니다. 즉, "스크롤바가 ___와 ___ 사이에 있을 때 이 스크롤 트리거가 활성화됩니다." 그런 다음, "스크롤" 이벤트를 디바운스하고 GSAP와 완벽하게 동기화된 다음 requestAnimationFrame에서만 업데이트를 수행합니다. 스크롤 위치만 봅니다. 기간. 즉, 속도가 빠릅니다.

 

ScrollTrigger는 자동으로 뷰포트/스크롤러 "크기 조정" 이벤트를 수신하고 그에 따라 모든 시작/종료 위치를 다시 계산합니다 (onRefresh). 실제로 크기 조정/새로 고침은 CPU 집약적이므로 크기 조정 이벤트에 200ms의 간격이 있을 때까지 기다린 후 작업을 시작합니다. 우리는 성능을 극대화 할 수있는 모든 기회를 찾았습니다.

 

IntersectionObserver 는 다음과 같은 면에서 다른 최신 브라우저의 기본 기능입니다.

  • 스크롤에 관계없이 요소가 들어가거나 나갈 때 감지하기 위해 지속적으로 요소를 "감시"합니다.
  • 그에 따라 애니메이션을 스크러빙하는 것과 같이 두 지점 사이의 요소 위치를 추적하는 데는 도움이되지 않습니다.
  • 예를 들어, 여러 요소를 보고 단일 콜백이 트리거되어 입력한 요소에서만 시차 애니메이션을 실행할 수 있습니다.

 

ScrollTrigger는 필요한 기능과 호환성이 없기 때문에 내부적으로 IntersectionObserver를 사용하지 않습니다. IntersectionObserver와 ScrollTrigger를 함께 사용할 수 있습니다.

 

 

내부에서 고정은 어떻게 작동합니까?

  • 고정된 요소는 일치하는 고정 너비 / 높이로 <div>에 즉시 래핑됩니다. "pin-spacer" 클래스가 해당 래퍼에 추가됩니다. DOM 내의 고정 요소가 "position: fixed"으로 전환되었을 때 붕괴되지 않도록 고정 요소가 DOM 내의 공간을 지탱하는 프록시 요소처럼 생각하세요.
  • 기본적으로 패딩은 pin-spacer의 하단(또는 오른쪽의 경우 horizontal: true)에 추가되어 [대부분의 경우] 사물이 더 아래/오른쪽으로 밀리게 됩니다. 고정된 요소의 고정이 풀리면 아래/오른쪽 컨텐츠가 따라잡힙니다. 예를 들어, 고정된 요소가 300px 동안 고정되어 있다면 300px의 패딩이 추가됩니다.
  • ScrollTrigger가 활성화되면(스크롤 위치가 시작과 끝 사이에 있을 때) 고정된 요소를 "position: fixed"로 설정하고 고정된 top/left/width/height 값으로 배치합니다. 스크롤러가 해당 뷰포트가 아닌 경우 "position: fixed"를 사용하지 않는 이유는 sub-scrolling이 깨지기 때문에, 순수 transform을 사용합니다. pinReparent가 true로 설정되면 (가능한 경우 피하는 것이 좋습니다), 고정 요소는 <body>로 재배치되고 스타일은 모양이 유지되도록 인라인으로 이동됩니다.
  • ScrollTrigger가 비활성화되면 고정된 요소가 원래 position 값으로 돌아가고 올바르게 배치하기 위해 transform이 적용됩니다.
  • 창/스크롤러의 크기가 조정되면 모든 ScrollTrigger가 시작/종료 위치를 다시 계산합니다(onRefresh). 이 프로세스의 일부로, pin-spacer가 DOM에서 제거되고 고정된 요소가 원래 CSS로 정확하게 측정되도록 다시 교체됩니다. 그런 다음 pin-spacer가 래퍼로 다시 교체됩니다.

 

transform만 사용하여 "position: fixed"를 회피하면 어떨까요? 많은 브라우저가 이 기술을 사용하여 일관되게 렌더링 하지 않습니다. 최근 브라우저에서는 스크롤 repaints가 다른 스레드에서 처리되기 때문에 시각적 결함이 있습니다. 놀랍게도, "position: fixed"는 전반적으로 성능이 뛰어난 것처럼 보였습니다. 스크롤을 위해서는 성능이 매우 중요합니다.

 

 

duration은 scrub : true에서 어떻게 작동합니까?

ScrollTrigger의 "scrub: true"가 있고 해당 ScrollTrigger에 타임라인 또는 트윈 애니메이션이 연결되어있는 경우, 해당 애니메이션 내 트윈의 duration은 트윈이 재생되는 총 거리에 대한 비율입니다. 애니메이션 사이의 거리 비율은 애니메이션의 총 지속 시간과 관련이 있습니다. 다음의 예를 사용하면, 가장 알기 쉬워집니다.

 

타임라인이 세 개 있다고 가정해 보겠습니다. 1초 간격, 3초 간격, 그리고 1초 간격입니다. 그리고 여기에 적용된 Scroll Trigger는 전체 뷰포트 높이의 거리에 대해 애니메이션됩니다. (트리거는 start: "center bottom"과 end: "center top" 값을 사용합니다).

 

scrub: true (또는 숫자)가 적용된 경우 첫 번째 트윈은 트리거 요소의 중심이 뷰 포트의 100% 지점(위부터, 뷰포트 하단)과 80% 지점(뷰포트의 상단)에서, 두 번째 트윈은 요소의 중심이 80% 지점과 20% 지점 사이에 있을 때 실행됩니다. 세 번째 트윈은 요소의 중심이 20% 지점과 0% 지점 사이에 있을 때 실행됩니다. 타임 라인의 총 지속 시간이 5초이기 때문입니다. 따라서 ⅕은 20%이고 ⅗는 60%입니다.

const tl = gsap.timeline({
  scrollTrigger: {
    trigger: ".trigger",
    start: "center bottom",
    end: "center top",
    scrub: true,
    markers: true
  }
});
tl.to(".box", {yPercent: 350, duration: 1})
tl.to(".box", {rotation: 360, duration: 3})
tl.to(".box", {xPercent: 350, duration: 1})

 

예를 들어, 모든 트윈의 duration을 동일한 숫자로 변경하면 100% -> 66%, 66% -> 33%, 33% -> 0%로 모두 백분율이 동일합니다. 이는 총 지속시간이 3이므로 β는 33%이기 때문입니다.



즉, duration 값은 타임라인의 총 시간과 비교해서 각 트윈 duration의 비율만큼 중요하지 않습니다.



애니메이션을 완료하기 위해 스크롤 거리를 길게 하는 경우 시작에서 종료까지의 거리에 영향을 미칩니다. 예를 들어 end: "+=4000"으로 설정하여 완료하는 데 많은 양의 스크롤이 필요하도록 할 수 있습니다.

 

 

Demo

각각 비디오 미리보기가 있는 일반적인 효과에 대한 ScrollTrigger 데모 목록을 만들었습니다. 키워드를 사용하여 관련 데모를 검색 할 수도 있습니다.

 

ScrollTrigger 데모 이해

 

콘텐츠 탐색

 

시차 효과

 

기본 스크롤 기술과 페어링

 

기타 효과

 

더 많은 것을 원하십니까? 사용자가 만든 ScrollTrigger 펜 컬렉션 또는 CodePen에서 ScrollTrigger 펜 모음을 확인하십시오.

 

 

반응형