고성능 시차

Robert Flack
Robert Flack

좋든 싫든 시차는 이제 생겨날 겁니다. 신중하게 사용하면 웹 앱에 깊이와 섬세함을 더할 수 있습니다. 하지만 문제는 시차를 효율적으로 처리하는 것이 어려울 수 있습니다. 이 도움말에서는 성능이 우수하면서도 효과적으로 작동하는 솔루션에 대해 크로스 브라우저입니다.

시차 삽화

요약

  • 시차 애니메이션을 만드는 데 스크롤 이벤트 또는 background-position를 사용하지 마세요.
  • CSS 3D 변환을 사용하여 더 정확한 시차 효과를 만들 수 있습니다.
  • 모바일 Safari의 경우 position: sticky를 사용하여 시차 효과를 확인합니다. 영향을 미칩니다

삽입형 솔루션이 필요하면 UI 요소 샘플 GitHub 저장소로 이동하여 패럴랙스 도우미 JS! 시차 스크롤러의 라이브 데모는 GitHub 저장소

문제 시차

먼저 시차를 달성하는 두 가지 일반적인 방법을 살펴보겠습니다. 특히 이 원칙이 우리의 목적에 적합하지 않은 이유를 명심해야 합니다.

나쁨: 스크롤 이벤트 사용

시차의 주요 요구사항은 스크롤이 결합되어야 한다는 것입니다. 대상: 페이지 스크롤 위치의 모든 변화, 시차 요소의 위치가 업데이트되어야 합니다. 간단한 말처럼 들릴 수 있지만, 비동기식으로 작동한다는 점입니다 이는 특히 이벤트를 스크롤하는 데 사용됩니다. 대부분의 브라우저에서 스크롤 이벤트는 '최선의 노력'으로 표시 광고의 모든 프레임에 게재되는 것은 살펴보겠습니다.

이 중요한 정보를 통해 우리는 왜 이런 일이 발생하지 않도록 해야 하는지 스크롤 이벤트를 기반으로 요소를 이동하는 JavaScript 기반 솔루션입니다. JavaScript는 시차가 시차에 맞춰 조정된다고 보장하지 않습니다 수동으로 조정할 수 있습니다. 이전 버전의 Mobile Safari에서 스크롤 이벤트는 스크롤이 끝날 때 배달되는 경우가 많기 때문에 JavaScript 기반 스크롤 효과입니다. 최신 버전은 스크롤 이벤트를 전송합니다. Chrome과 마찬가지로 '최선의 지원'으로 기반으로 합니다 만약 기본 스레드가 다른 작업으로 인해 사용 중이므로 스크롤 이벤트가 전달되지 않습니다. 시차 효과가 사라집니다.

불량: background-position 업데이트 중

피해야 할 또 다른 상황은 모든 프레임에 그림을 그리는 것입니다. 다양한 솔루션 시차 효과를 제공하기 위해 background-position 변경을 시도합니다. 브라우저가 스크롤 시 페이지의 영향을 받은 부분을 다시 페인팅하고 애니메이션에 상당한 버벅거림을 발생시킬 만큼 비용이 많이 들 수 있습니다.

시차 운동이라는 이점을 실현하려면 빠른 속성 (현재는 변형 및 불투명도)을 지원하며 스크롤 이벤트에 의존하지 않습니다.

3D CSS

스콧 켈럼키스 클라크 모두 시차 모션을 달성하기 위해 CSS 3D를 사용하는 영역에서 상당한 작업을 수행했습니다. 사용하는 기술은 실질적으로 다음과 같습니다.

  • overflow-y: scroll를 사용하여 스크롤하도록 포함 요소를 설정합니다 (아마도 overflow-x: hidden).
  • 동일한 요소에 perspective 값 및 perspective-origin top left 또는 0 0로 설정합니다.
  • 해당 요소의 하위 요소에 변환을 Z로 적용하고 크기를 다시 조정합니다. 최대 패럴랙스 모션을 제공할 수 있습니다.

이 접근 방식의 CSS는 다음과 같습니다.

.container {
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  overflow-y: scroll;
  perspective: 1px;
  perspective-origin: 0 0;
}

.parallax-child {
  transform-origin: 0 0;
  transform: translateZ(-2px) scale(3);
}

다음과 같은 HTML 코드를 가정합니다.

<div class="container">
    <div class="parallax-child"></div>
</div>

원근감을 위해 배율 조정

하위 요소를 뒤로 밀면 Perspective 값을 설정합니다. 이를 통해 확장되어야 하는 양을 계산할 수 있습니다. (투시 - 거리) / 원근 방정식입니다. 우리가 아마도 시차 요소가 시차를 만들고 싶지만 우리가 만든 크기로 표시되도록 할 수 있습니다. 그대로 두지 않고 이러한 방식으로 확장해야 합니다.

위 코드의 경우 원근은 1px이며 parallax-child의 Z 거리는 -2px입니다. 즉, 요소에는 3x로 수직 확장할 수 있으며, 이는 코드에 연결된 값입니다. scale(3)입니다.

translateZ 값이 적용되지 않은 콘텐츠의 경우 다음 작업을 할 수 있습니다. 0으로 대체합니다. 이는 척도가 (관점 - 0) / 1로 확장되어 확장된 것입니다. 위아래로 이동하지 않아도 됩니다 정말 편리합니다.

이 접근 방식의 작동 방식

이 API가 작동하는 이유를 명확히 하는 것이 중요합니다. 왜냐하면 곧 알게 될 것입니다. 스크롤은 사실상 변환이므로 accelerated; 대부분 GPU와 함께 레이어를 이동하는 작업이 포함됩니다. 원근법, 스크롤링, 잡동사니 같은 스크롤 요소와 그 하위 요소를 비교할 때 1:1로 발생합니다. 요소를 300px까지 아래로 스크롤하면 하위 요소가 위로 변환됩니다. 300px만큼 차이가 납니다.

그러나 원근법 값을 스크롤 요소에 적용하면 엉망이 됩니다. 이 프로세스를 통해 스크롤 변환을 뒷받침하는 행렬을 변경합니다. 이제 300px로 스크롤하면 선택한 perspectivetranslateZ 값입니다. 요소에 translateZ 값이 0이면 이전처럼 1:1로 스크롤되지만 하위 요소 다른 각도로 스크롤되며 있습니다. 실제 결과: 시차 운동 그리고 매우 중요한 것은 자동으로 스크롤하는 역할을 합니다. scroll 이벤트를 수신 대기하거나 background-position를 변경할 필요가 없습니다.

연고를 타는 파리: 모바일 사파리

모든 효과에는 주의사항이 있으며 변환과 관련하여 중요한 한 가지는 하위 요소에 대한 3D 효과 보존 만약 원근법이 있는 요소와 시차 하위 요소 간의 계층 구조를 3D 원근법은 '평면화'되어 효과가 사라집니다.

<div class="container">
    <div class="parallax-container">
    <div class="parallax-child"></div>
    </div>
</div>

위의 HTML에서 .parallax-container은 새 코드이며 실질적으로 perspective 값을 평면화하면 시차 효과가 사라집니다. 해결책은 대부분의 경우 매우 간단합니다. transform-style: preserve-3d를 추가하면 됩니다. 을 추가하여 3D 효과 (예: 원근법)를 값)이 있습니다.

.parallax-container {
  transform-style: preserve-3d;
}

그러나 모바일 Safari의 경우에는 좀 더 복잡합니다. 컨테이너 요소에 overflow-y: scroll를 적용하는 것은 기술적으로는 작동하지만 스크롤 요소를 플링할 수 있는 비용. 해결책은 -webkit-overflow-scrolling: touch 하지만 perspective도 평면화합니다. 시차를 받지 않게 됩니다.

점진적인 개선의 관점에서 보면 이것은 아마도 그다지 그리 어려운 것이 아닐 것입니다. 있습니다. 모든 상황에서 시차를 맞출 수 없더라도 앱은 계속 작동하지만 해결 방법을 찾는 것이 좋습니다.

position: sticky이(가) 구했습니다!

실제로 position: sticky 형태의 도움이 있습니다. 요소가 '고정'되도록 허용 표시 영역 또는 지정된 상위 요소의 상단으로 볼 수 있습니다. 사양은 대부분 그렇듯이 상당히 무겁지만 유용한 작은 보석이 있습니다.

언뜻 보기에는 그다지 중요하지 않은 것처럼 보일 수 있지만, 중요한 점은 그 문장은 정확히 어떤 요소의 접착성이 얼마나 다음과 같이 계산됩니다. "오프셋은 가장 가까운 상위 항목을 참조하여 계산됩니다. 스크롤 상자가 표시됩니다. 즉, 고정 요소를 이동할 거리 (다른 요소 또는 표시 영역에 연결된 것으로 표시되기 위한) 이후가 아닌 다른 변환이 적용되기 전에 계산됩니다. 다시 말해 이는 앞서 살펴본 스크롤 예와 매우 흡사하며, 오프셋이 계산되어 300픽셀을 사용하면 관점이나 다른 변환을 사용할 수 있는 새로운 기회가 있습니다. 300픽셀 오프셋 값을 조작하여 요소

position: -webkit-sticky를 시차 요소에 적용하면 사실상 "역방향" -webkit-overflow-scrolling: touch의 평면화 효과 이렇게 하면 시차 요소가 가장 가까운 스크롤 상자가 있는 상위 요소를 정의합니다. 이 경우에는 .container입니다. 그런 다음 이전과 유사하게 .parallax-containerperspective 값을 적용합니다. 계산된 스크롤 오프셋을 변경하고 시차 효과를 생성합니다.

<div class="container">
    <div class="parallax-container">
    <div class="parallax-child"></div>
    </div>
</div>
.container {
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
}

.parallax-container {
  perspective: 1px;
}

.parallax-child {
  position: -webkit-sticky;
  top: 0px;
  transform: translate(-2px) scale(3);
}

이렇게 하면 모바일 Safari의 시차 효과가 복원됩니다. 둥글게!

고정 포지셔닝 주의사항

여기에는 차이가 있지만 position: sticky는 패럴랙스 역학의 한 부분을 살펴보았습니다. 고정 포지셔닝에서는 요소를 윗면에 비고정 버전은 그렇지 않습니다. 즉, 접점이 있는 시차는 다음을 포함하지 않은 시차의 역이 됩니다.

  • position: sticky사용하면 요소가 z=0에 가까울수록 요소가 적을 것입니다. 움직입니다.
  • position: sticky없는 경우 요소가 z=0에 가까울수록 더 가깝습니다 움직입니다.

모두 추상적으로 느껴지신다면 로버트 플랙의 데모를 살펴보세요. 요소가 고정을 사용하거나 사용하지 않을 때 어떻게 다르게 동작하는지 보여줍니다. 있습니다. 차이점을 확인하려면 Chrome Canary (버전 56)가 필요합니다. Safari에서 사용할 수 있습니다.

패럴랙스 원근 스크린샷

로버트 플랙의 데모에서 그 방법을 보여줍니다. position: sticky는 시차 스크롤에 영향을 미칩니다.

다양한 버그 및 해결 방법

그러나 다른 모든 것과 마찬가지로, 여전히 개선해야 할 평활화:

  • 고정 지원이 일관되지 않습니다. 다음에서 지원이 아직 구현 중입니다. Chrome, Edge는 완전히 지원되지 않으며, Firefox는 스티키가 원근 변환과 결합될 때 페인팅 버그가 발생합니다. 이러한 작은 코드를 추가하여 position: sticky( -webkit- 접두사 버전)(필요한 경우 모바일 Safari용) 전용입니다.
  • 효과는 '제대로 되지 않습니다' 제공됩니다 Edge가 이는 일반적으로 좋은 것이지만 이 경우에는 스크롤하는 동안 시점 변경을 감지하지 못하도록 합니다. 이 문제를 해결하려면 Edge를 비 OS 스크롤 방식으로 전환하는 것처럼 보이므로 관점의 변화를 고려합니다
  • '페이지 콘텐츠가 엄청나네요!' 많은 브라우저에서 아쉽게도 Chrome과 Safari에서는 페이지 콘텐츠의 크기를 조정할 수 있습니다 의견을 전달하지 않습니다. 그래서 예를 들어 어떤 요소에 3배 배율을 적용한다면 스크롤바 등을 볼 수 있습니다. perspective이(가) 적용되었습니다. 이 문제는 오른쪽 하단 모서리에서 요소를 크기 조정 (transform-origin: bottom right 사용)합니다. 이렇게 하면 크기가 커지는 요소가 오른쪽 하단 안으로 커지기 때문에 '제외 지역' (일반적으로 왼쪽 상단) 스크롤 가능한 영역 스크롤 가능 제외 영역의 콘텐츠를 보거나 스크롤할 수 없습니다.

결론

시차는 신중하게 사용하면 재미있는 효과입니다. 보시다시피 성능, 스크롤 결합, 교차 브라우저 방식으로 구현할 수 있습니다. 이를 위해서는 약간의 수학적 꿈이 필요하고 원하는 효과를 얻기 위해 작은 도우미 라이브러리를 래핑했습니다. UI 요소 샘플 GitHub 저장소에서 확인할 수 있습니다.

플레이해 보시고 어떻게 지내셨는지 알려주세요.