폴라로이드 이미지를 뒤집는 CSS 무한 슬라이더 PlatoBlockchain Data Intelligence. 수직 검색. 일체 포함.

폴라로이드 이미지를 통해 뒤집는 CSS 무한 슬라이더

마지막 기사에서, 우리는 원형 방향으로 회전하는 매우 멋진 작은 슬라이더(또는 원하는 경우 "회전 목마")를 만들었습니다. 이번에는 폴라로이드 이미지 더미를 뒤집는 사진을 만들 것입니다.

멋지죠? 풀어야 할 것이 많기 때문에 아직 코드를 자세히 보지 마십시오. 나랑 같이 할래?

CSS 슬라이더 시리즈

기본 설정

이 슬라이더에 대한 대부분의 HTML 및 CSS는 지난번에 만든 원형과 유사합니다. 사실 우리는 똑같은 마크업을 사용하고 있습니다.

그리고 이것은 부모를 설정하는 기본 CSS입니다. .gallery 모든 이미지가 서로의 위에 하나씩 쌓이는 그리드로서의 컨테이너:

.gallery  {
  display: grid;
  width: 220px; /* controls the size */
}
.gallery > img {
  grid-area: 1 / 1;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border: 10px solid #f2f2f2;
  box-shadow: 0 0 4px #0007;
}

지금까지 복잡한 것은 없습니다. 폴라로이드 느낌의 사진 스타일도 일부만 사용하고 있습니다. borderbox-shadow. 더 잘할 수 있을 것이므로 자유롭게 장식 스타일을 가지고 놀아보세요! 우리는 가장 까다로운 부분인 애니메이션에 대부분의 초점을 맞출 것입니다.

속임수는 무엇입니까?

이 슬라이더의 논리는 이미지의 스택 순서에 따라 달라집니다. z-index. 모든 이미지는 같은 것으로 시작합니다. z-index 가치 (2) 논리적으로 스택 맨 위에 마지막 이미지를 만듭니다.

마지막 이미지를 가져와 스택의 다음 이미지가 나타날 때까지 오른쪽으로 밉니다. 그런 다음 이미지를 줄입니다. z-index 그런 다음 데크에 다시 밀어 넣습니다. 그리고 그 이후로 z-index 값이 나머지 이미지보다 낮으면 스택의 마지막 이미지가 됩니다.

다음은 트릭을 보여주는 제거된 데모입니다. 이미지를 가리키면 애니메이션이 활성화됩니다.

이제 모든 이미지에 동일한 트릭이 적용된다고 상상해 보십시오. 다음은 패턴을 사용하는 경우입니다. :nth-child() 이미지를 구별하기 위한 의사 선택기:

  • 마지막 이미지를 슬라이드(N). 다음 이미지가 표시됩니다(N - 1).
  • 다음 이미지를 슬라이드합니다(N - 1). 다음 이미지가 표시됩니다(N - 2)
  • 다음 이미지를 슬라이드합니다(N - 2). 다음 이미지가 표시됩니다(N - 3)
  • (첫 번째 이미지에 도달할 때까지 동일한 프로세스를 계속합니다.)
  • 첫 번째 이미지(1). 마지막 이미지(N)가 다시 표시됩니다.

그것은 우리의 무한 슬라이더입니다!

애니메이션 해부

이전 기사를 기억한다면 하나의 애니메이션만 정의하고 각 이미지를 제어하기 위해 지연을 두고 재생했습니다. 우리는 여기서 같은 일을 할 것입니다. 먼저 애니메이션의 타임라인을 시각화해 보겠습니다. 세 개의 이미지로 시작한 다음 나중에 임의의 수에 대해 일반화합니다(N) 이미지.

폴라로이드 이미지를 통해 뒤집는 CSS 무한 슬라이더

애니메이션은 "오른쪽으로 슬라이드", "왼쪽으로 슬라이드" 및 "움직이지 않음"의 세 부분으로 나뉩니다. 각 이미지 사이의 지연을 쉽게 식별할 수 있습니다. 첫 번째 이미지가 0s, 지속 시간은 다음과 같습니다. 6s, 그러면 두 번째는 에서 시작됩니다. -2s 그리고 세 번째는 -4s.

.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 6s / 3 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 6s / 3 */

또한 "don't move" 부분이 전체 애니메이션의 XNUMX/XNUMX를 차지하는 것을 볼 수 있습니다(2*100%/3) "오른쪽으로 밀기" 및 "왼쪽으로 밀기" 부분은 전체의 XNUMX/XNUMX을 차지하므로 각각은 다음과 같습니다. 100%/6 전체 애니메이션의

다음과 같이 애니메이션 키프레임을 작성할 수 있습니다.

@keyframes slide {
  0%     { transform: translateX(0%); }
  16.67% { transform: translateX(120%); }
  33.34% { transform: translateX(0%); }
  100%   { transform: translateX(0%); } 
}

120% 임의의 값입니다. 그보다 더 큰 무언가가 필요했어 100%. 이미지는 나머지 이미지에서 오른쪽으로 슬라이드해야 합니다. 그러기 위해서는 적어도 100% 그것의 크기. 그래서 내가 갔다 120% — 추가 공간 확보.

이제 우리는 z-index. 이미지를 업데이트해야 한다는 점을 잊지 마세요. z-index 가치 시간 내에 그것은 더미의 오른쪽으로 미끄러지고, 전에 더미 바닥으로 다시 밀어 넣습니다.

@keyframes slide {
  0%     { transform: translateX(0%);   z-index: 2; }
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; } /* we update the z-order here */
  33.34% { transform: translateX(0%);   z-index: 1; }
  100%   { transform: translateX(0% );  z-index: 1; }  
}

하나의 상태를 정의하는 대신 16.67% (100%/6) 타임라인의 지점에서 거의 동일한 지점(16.66%16.67%) 어디 z-index 이미지를 데크로 다시 슬라이드하기 전에 값이 감소합니다.

이 모든 것을 하나로 합치면 다음과 같은 일이 발생합니다.

흠 슬라이딩 부분은 잘 되는 것 같은데 쌓이는 순서가 다 뒤죽박죽! 상단 이미지가 뒤로 이동하기 때문에 애니메이션이 멋지게 시작되지만... 후속 이미지는 이를 따르지 않습니다. 알아차리면 다음 이미지가 그 위에서 깜박이기 전에 시퀀스의 두 번째 이미지가 스택의 맨 위로 돌아갑니다.

우리는 면밀히 따를 필요가 있습니다 z-index 변화. 처음에는 모든 이미지가 z-index: 2. 즉, 스태킹 순서는 다음과 같아야 합니다.

Our eyes 👀 --> 3rd (2) | 2nd (2) | 1st (2)

세 번째 이미지를 슬라이드하고 업데이트합니다. z-index 이 주문을 받으려면:

Our eyes 👀 --> 2nd (2) | 1st (2) | 3rd (1)

우리는 두 번째 것과 동일하게 수행합니다.

Our eyes 👀 --> 1st (2) | 3rd (1) | 2nd (1)

…그리고 첫 번째 것:

Our eyes 👀 --> 3rd (1) | 2nd (1) | 1st (1)

우리는 그렇게 하고 모든 것이 괜찮은 것 같습니다. 그러나 실제로는 그렇지 않습니다! 첫 번째 이미지가 뒤로 이동하면 세 번째 이미지가 또 다른 반복을 시작합니다. z-index: 2:

Our eyes 👀 --> 3rd (2) | 2nd (1) | 1st (1)

따라서 실제로는 모든 이미지를 z-index: 2 조금도! 이미지가 움직이지 않는 경우(예: 애니메이션의 "움직이지 않음" 부분) z-index is 1. 세 번째 이미지를 슬라이드하고 업데이트하면 z-index ~의 가치 21, 그것은 상단에 남아있을 것입니다! 모든 이미지가 같을 때 z-index, 소스 순서의 마지막 이미지(이 경우 세 번째 이미지)가 스택 맨 위에 있습니다. 세 번째 이미지를 슬라이드하면 다음과 같은 결과가 나타납니다.

Our eyes 👀 --> 3rd (1) | 2nd (1) | 1st (1)

세 번째 이미지는 여전히 맨 위에 있고 그 직후 애니메이션이 다시 시작되면 두 번째 이미지를 맨 위로 이동합니다. z-index: 2:

Our eyes 👀 --> 2nd (2) | 3rd (1) | 1st (1)

슬라이드하면 다음을 얻습니다.

Our eyes 👀 --> 3rd (1) | 2nd (1) | 1st (1)

그런 다음 첫 번째 이미지가 맨 위로 이동합니다.

Our eyes 👀 --> 1st(2) | 3rd (1) | 2nd (1)

좋아, 나는 길을 잃었다. 그러면 모든 논리가 잘못된 것입니까?

알아요, 혼란스럽습니다. 그러나 우리의 논리가 완전히 틀린 것은 아닙니다. 애니메이션을 약간만 수정하면 모든 것이 원하는 방식으로 작동합니다. 요령은 올바르게 재설정하는 것입니다. z-index.

세 번째 이미지가 맨 위에 있는 상황을 가정해 보겠습니다.

Our eyes 👀 -->  3rd (2) | 2nd (1) | 1st (1)

우리는 세 번째 이미지를 슬라이드하고 z-index 그것을 위에 유지합니다. 우리가 해야 할 일은 z-index 두 번째 이미지의. 따라서 데크에서 세 번째 이미지를 슬라이드하기 전에 z-index 두 번째 이미지의 2.

다시 말해, 우리는 z-index 애니메이션이 끝나기 전 두 번째 이미지의

Z-인덱스가 증가하거나 감소하는 위치에 대한 표시기를 사용하여 애니메이션 부분을 다이어그램으로 표시합니다.
폴라로이드 이미지를 통해 뒤집는 CSS 무한 슬라이더

녹색 더하기 기호는 증가를 나타냅니다. z-index2, 빨간색 빼기 기호는 z-index: 1. 두 번째 이미지는 z-index: 2, 그런 다음 업데이트합니다. 1 갑판에서 미끄러질 때. 그러나 첫 번째 이미지가 데크에서 멀어지기 전에 z-index 다시 두 번째 이미지의 2. 이렇게 하면 두 이미지가 동일한지 확인할 수 있습니다. z-index, 그러나 여전히 세 번째는 나중에 DOM에 나타나기 때문에 맨 위에 남습니다. 그러나 세 번째 이미지가 슬라이드된 후 z-index 업데이트되면 맨 아래로 이동합니다.

애니메이션의 XNUMX/XNUMX이므로 그에 따라 키프레임을 업데이트하겠습니다.

@keyframes slide {
  0%     { transform: translateX(0%);   z-index: 2; }
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; } /* we update the z-order here */
  33.34% { transform: translateX(0%);   z-index: 1; }
  66.33% { transform: translateX(0%);   z-index: 1; }
  66.34% { transform: translateX(0%);   z-index: 2; } /* and also here */
  100%   { transform: translateX(0%);   z-index: 2; }  
}

조금 나아졌지만 여전히 아주 거기. 또 다른 문제가 있습니다…

오 안돼, 이건 절대 끝나지 않을거야!

걱정하지 마세요. 이 문제는 마지막 이미지가 관련된 경우에만 발생하기 때문에 키프레임을 다시 변경하지 않을 것입니다. 문제를 해결하기 위해 마지막 이미지에 특별히 "특별한" 키프레임 애니메이션을 만들 수 있습니다.

첫 번째 이미지가 맨 위에 있으면 다음과 같은 상황입니다.

Our eyes 👀 -->  1st (2) | 3rd (1) | 2nd (1)

우리가 만든 이전 조정을 고려하면 첫 번째 이미지가 슬라이드되기 전에 세 번째 이미지가 맨 위로 점프합니다. 이 상황에서만 발생합니다. 첫 번째 이미지 이후에 이동하는 다음 이미지가 지난 DOM에서 더 높은 순서를 가진 이미지. 나머지 이미지는 괜찮습니다. N다음, N - 1, 그런 다음 우리는 3221...하지만 우리는 1N.

이를 방지하기 위해 마지막 이미지에 다음 키프레임을 사용합니다.

@keyframes slide-last {
  0%     { transform: translateX(0%);   z-index: 2;}
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; } /* we update the z-order here */
  33.34% { transform: translateX(0%);   z-index: 1; }
  83.33% { transform: translateX(0%);   z-index: 1; }
  83.34% { transform: translateX(0%);   z-index: 2; } /* and also here */
  100%   { transform: translateX(0%);   z-index: 2; }
}

우리는 재설정 z-index 첫 번째 이미지가 더미에서 나올 때 애니메이션을 통해 값 5/6(XNUMX/XNUMX 대신). 그래서 우리는 어떤 점프도 볼 수 없습니다!

짜잔! 무한 슬라이더가 이제 완벽해졌습니다! 영광스러운 최종 코드는 다음과 같습니다.

.gallery > img {
  animation: slide 6s infinite;
}
.gallery > img:last-child {
  animation-name: slide-last;
}
.gallery > img:nth-child(2) { animation-delay: -2s; } 
.gallery > img:nth-child(3) { animation-delay: -4s; }

@keyframes slide {
  0% { transform: translateX(0%); z-index: 2; }
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; } 
  33.34% { transform: translateX(0%); z-index: 1; }
  66.33% { transform: translateX(0%); z-index: 1; }
  66.34% { transform: translateX(0%); z-index: 2; } 
  100% { transform: translateX(0%); z-index: 2; }
}
@keyframes slide-last {
  0% { transform: translateX(0%); z-index: 2; }
  16.66% { transform: translateX(120%); z-index: 2; }
  16.67% { transform: translateX(120%); z-index: 1; }
  33.34% { transform: translateX(0%); z-index: 1; }
  83.33% { transform: translateX(0%); z-index: 1; }
  83.34% { transform: translateX(0%); z-index: 2; } 
  100%  { transform: translateX(0%); z-index: 2; }
}

여러 이미지 지원

이제 애니메이션이 XNUMX개의 이미지에 대해 작동하므로 임의의 숫자(N) 이미지. 그러나 먼저 중복을 피하기 위해 애니메이션을 분할하여 작업을 약간 최적화할 수 있습니다.

.gallery > img {
  z-index: 2;
  animation: 
    slide 6s infinite,
    z-order 6s infinite steps(1);
}
.gallery > img:last-child {
  animation-name: slide, z-order-last;
}
.gallery > img:nth-child(2) { animation-delay: -2s; } 
.gallery > img:nth-child(3) { animation-delay: -4s; }

@keyframes slide {
  16.67% { transform: translateX(120%); }
  33.33% { transform: translateX(0%); }
}
@keyframes z-order {
  16.67%,
  33.33% { z-index: 1; }
  66.33% { z-index: 2; }
}
@keyframes z-order-last {
  16.67%,
  33.33% { z-index: 1; }
  83.33% { z-index: 2; }
}

이제 훨씬 적은 코드! 우리는 슬라이딩 부분에 대해 하나의 애니메이션을 만들고 z-index 업데이트. 우리가 사용하는 참고 steps(1) 를 시청하여 이에 대해 더 많은 정보를 얻을 수 있습니다. z-index 생기. 갑자기 바꾸고 싶기 때문이다. z-index 부드러운 움직임을 원하는 슬라이딩 애니메이션과 달리

이제 코드를 읽고 유지하기가 더 쉬워졌으므로 많은 이미지를 지원하는 방법을 더 잘 파악할 수 있습니다. 우리가 해야 할 일은 애니메이션 지연과 키프레임 비율을 업데이트하는 것입니다. 원형 슬라이더에서 여러 이미지를 지원하기 위해 지난 기사에서 만든 것과 똑같은 루프를 사용할 수 있기 때문에 지연이 쉽습니다.

@for $i from 2 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
    animation-delay: calc(#{(1 - $i)/$n}*6s);
  }
}

이는 우리가 바닐라 CSS에서 Sass로 이동하고 있음을 의미합니다. 다음으로 타임라인이 어떻게 확장되는지 상상해야 합니다. N 이미지. 애니메이션이 세 단계로 진행된다는 사실을 잊지 마십시오.

화살표가 있는 일련의 선으로 애니메이션의 세 부분을 표시합니다.
폴라로이드 이미지를 통해 뒤집는 CSS 무한 슬라이더

"오른쪽으로 밀기" 및 "왼쪽으로 밀기" 후에는 나머지 이미지가 시퀀스를 통과할 때까지 이미지가 그대로 있어야 합니다. 따라서 "움직이지 않음" 부분은 (N - 1) "오른쪽으로 슬라이드" 및 "왼쪽으로 슬라이드". 그리고 한 번의 반복 내에서 N 이미지가 미끄러집니다. 따라서 "오른쪽으로 밀기"와 "왼쪽으로 밀기"는 모두 100%/N 전체 애니메이션 타임라인의 이미지는 더미에서 멀어집니다. (100%/N)/2 그리고 다시 슬라이드 100%/N .

우리는 이것을 바꿀 수 있습니다:

@keyframes slide {
  16.67% { transform: translateX(120%); }
  33.33% { transform: translateX(0%); }
}

…이에:

@keyframes slide {
  #{50/$n}%  { transform: translateX(120%); }
  #{100/$n}% { transform: translateX(0%); }
}

우리가 교체하면 N3, 우리는 얻는다. 16.67%33.33% 있을 때 3 스택의 이미지. 다음과 같은 쌓임 순서와 동일한 논리입니다.

@keyframes z-order {
  #{50/$n}%,
  #{100/$n}% { z-index: 1; }
  66.33% { z-index: 2; }
}

아직 업데이트가 필요합니다. 66.33% 가리키다. 이미지가 재설정되는 곳이어야합니다. z-index 애니메이션이 끝나기 전에 그와 동시에 다음 이미지가 미끄러지기 시작합니다. 슬라이딩 부분이 걸리기 때문에 100%/N, 재설정은 다음에 발생해야 합니다. 100% - 100%/N:

@keyframes z-order {
  #{50/$n}%,
  #{100/$n}% { z-index: 1; }
  #{100 - 100/$n}% { z-index: 2; }
}

그러나 우리를 위해 z-order-last 애니메이션이 작동하려면 시퀀스에서 약간 나중에 발생해야 합니다. 마지막 이미지에 대해 수행한 수정 사항을 기억하십니까? 재설정 z-index 값은 첫 번째 이미지가 미끄러지기 시작할 때가 아니라 더미에서 나올 때 발생해야 합니다. 키프레임에서도 동일한 추론을 사용할 수 있습니다.

@keyframes z-order-last {
  #{50/$n}%,
  #{100/$n}% { z-index: 1; }
  #{100 - 50/$n}% { z-index: 2; }
}

끝났습니다! 다음은 XNUMX개의 이미지를 사용할 때 얻은 결과입니다.

좀 더 멋지게 만들기 위해 회전 터치를 추가할 수 있습니다.

내가 한 모든 것은 추가입니다 rotate(var(--r)) ~로 transform 재산. 루프 내부, --r 임의의 각도로 정의됩니다.

@for $i from 1 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
    --r: #{(-20 + random(40))*1deg}; /* a random angle between -20deg and 20deg */
  }
}

이미지 일부가 스택 뒤쪽으로 점프하는 것을 가끔 볼 수 있기 때문에 회전으로 인해 작은 결함이 발생하지만 큰 문제는 아닙니다.

최대 포장

모든 z-index 일은 큰 균형을 잡는 행위였죠? 이 연습을 하기 전에 스택 순서가 어떻게 작동하는지 잘 모르겠다면 지금 훨씬 더 나은 아이디어를 갖게 될 것입니다! 일부 설명을 따르기 어렵다면 기사를 다시 읽어보고 연필과 종이로 사물을 지도로 그리다. 트릭을 더 잘 이해하기 위해 다른 수의 이미지를 사용하여 애니메이션의 각 단계를 설명하십시오.

지난번에는 몇 가지 기하학적 기법을 사용하여 전체 시퀀스 후 첫 번째 이미지로 다시 회전하는 원형 슬라이더를 만들었습니다. 이번에는 다음을 사용하여 유사한 트릭을 수행했습니다. z-index. 두 경우 모두 연속 애니메이션을 시뮬레이션하기 위해 이미지를 복제하지 않았으며 계산을 돕기 위해 JavaScript에 도달하지도 않았습니다.

다음에는 3D 슬라이더를 만들어 보겠습니다. 계속 지켜봐!

타임 스탬프 :

더보기 CSS 트릭