Thanh trượt CSS Infinite 3D PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

CSS Thanh trượt 3D vô hạn

Trong loạt bài này, chúng tôi đã tạo thanh trượt hình ảnh không có gì ngoài HTML và CSS. Ý tưởng là chúng ta có thể sử dụng cùng một mã đánh dấu nhưng CSS khác nhau để nhận được các kết quả cực kỳ khác nhau, bất kể chúng ta đưa vào bao nhiêu hình ảnh. Chúng tôi bắt đầu với một thanh trượt tròn xoay vô tận, giống như một con quay thần tài giữ các hình ảnh. Sau đó, chúng tôi tạo một cái lật qua một chồng ảnh.

Lần này, chúng ta đang đi sâu vào chiều thứ ba. Thoạt nhìn nó có vẻ khó, nhưng rất nhiều đoạn mã mà chúng ta đang xem chính xác là những gì chúng ta đã sử dụng trong hai bài viết đầu tiên của loạt bài này, với một số sửa đổi. Vì vậy, nếu bây giờ bạn mới tham gia vào loạt bài này, tôi khuyên bạn nên xem qua những phần khác để biết ngữ cảnh về các khái niệm mà chúng tôi đang sử dụng ở đây.

Chuỗi thanh trượt CSS

Đây là những gì chúng tôi đang hướng tới:

Thoạt nhìn, có vẻ như chúng ta có một khối lập phương xoay với bốn hình ảnh. Nhưng trên thực tế, chúng ta đang xử lý tổng cộng sáu hình ảnh. Đây là thanh trượt từ một góc độ khác:

Bây giờ chúng ta đã có hình dung rõ ràng về cách sắp xếp các hình ảnh, hãy phân tích mã để xem cách chúng ta đạt được điều đó.

thiết lập cơ bản

HTML giống như phần còn lại của các thanh trượt mà chúng tôi đã sử dụng cho các thanh trượt khác:

Và một lần nữa, chúng tôi đang sử dụng CSS Grid để đặt các hình ảnh trong một ngăn xếp, chồng lên nhau:

.gallery {
  display: grid;
}
.gallery > img {
  grid-area: 1 / 1;
  width: 160px;
  aspect-ratio: 1;
  object-fit: cover;
}

Các hình ảnh động

Logic cho thanh trượt này rất giống với thanh trượt tròn từ bài viết đầu tiên. Trên thực tế, nếu bạn xem lại video ở trên, bạn có thể thấy rằng các hình ảnh được đặt theo cách tạo ra một đa giác. Sau khi xoay hoàn toàn, nó sẽ quay lại hình ảnh đầu tiên.

Chúng tôi dựa vào CSS transform-originanimation-delay thuộc tính cho thanh trượt đầu tiên đó. Hoạt hình tương tự được áp dụng cho tất cả các thành phần hình ảnh xoay quanh cùng một điểm. Sau đó, bằng cách sử dụng các độ trễ khác nhau, chúng tôi đặt tất cả các hình ảnh xung quanh một vòng tròn lớn một cách chính xác.

Việc triển khai sẽ hơi khác một chút đối với thanh trượt 3D của chúng tôi. sử dụng transform-origin sẽ không hoạt động ở đây vì chúng tôi đang làm việc ở chế độ 3D, vì vậy chúng tôi sẽ sử dụng transform thay vào đó để đặt chính xác tất cả các hình ảnh, sau đó xoay vùng chứa.

Chúng tôi đang tiếp cận với Sass một lần nữa để chúng tôi có thể lặp lại số lượng hình ảnh và áp dụng các biến đổi của mình:

@for $i from 1 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
     transform: 
       rotate(#{360*($i - 1) / $n}deg) /* 1 */
       translateY(50% / math.tan(180deg / $n)) /* 2 */ 
       rotateX(90deg); /* 3 */
  }
}

Bạn có thể thắc mắc tại sao chúng tôi lại nhảy thẳng vào Sass. Chúng tôi đã bắt đầu với một số lượng hình ảnh cố định bằng cách sử dụng vanilla CSS trong các bài viết khác trước khi tổng quát hóa mã bằng Sass để giải thích cho bất kỳ số lượng nào (N) của hình ảnh. Chà, tôi nghĩ bây giờ bạn đã hiểu ý tưởng và chúng ta có thể loại bỏ tất cả công việc khám phá đó để đi đến triển khai thực tế.

Sản phẩm transform thuộc tính đang nhận ba giá trị mà tôi đã minh họa ở đây:

CSS Thanh trượt 3D vô hạn

Trước tiên, chúng tôi xoay tất cả các hình ảnh lên nhau. Góc quay phụ thuộc vào số lượng ảnh. Vì N hình ảnh, chúng tôi có một gia số bằng 360deg/N. Sau đó chúng ta translate tất cả các hình ảnh bằng nhau theo cách làm cho các điểm trung tâm của chúng gặp nhau ở các cạnh.

Hiển thị chồng hình ảnh được sắp xếp phẳng trong một vòng tròn với một đường màu đỏ chạy qua điểm trung tâm của hình ảnh.
CSS Thanh trượt 3D vô hạn

Có một số hình học nhàm chán giúp giải thích cách thức hoạt động của tất cả những thứ này, nhưng khoảng cách bằng 50%/tan(180deg/N). Chúng tôi đã xử lý một phương trình tương tự khi tạo thanh trượt tròn ( transform-origin: 50% 50%/sin(180deg/N) ).

Cuối cùng, chúng tôi xoay hình ảnh xung quanh trục x bằng cách 90deg để có được sự sắp xếp chúng tôi muốn. Đây là video minh họa hoạt động của vòng quay cuối cùng:

Bây giờ tất cả những gì chúng ta phải làm là xoay toàn bộ vùng chứa để tạo thanh trượt vô hạn.

.gallery {
  transform-style: preserve-3d;
  --_t: perspective(280px) rotateX(-90deg);
  animation: r 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@keyframes r {
  0%, 3% {transform: var(--_t) rotate(0deg); }
  @for $i from 1 to $n {
    #{($i/$n)*100 - 2}%, 
    #{($i/$n)*100 + 3}% {
      transform: var(--_t) rotate(#{($i / $n) * -360}deg);
    }  
  }
  98%, 100% { transform: var(--_t) rotate(-360deg); }
}

Đoạn mã đó có thể khó hiểu, vì vậy chúng ta hãy lùi lại một chút và xem lại hoạt ảnh mà chúng ta đã tạo cho thanh trượt tròn. Đây là những gì chúng tôi đã viết trong bài báo đầu tiên đó:

.gallery {
  animation: m 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@keyframes m {
  0%, 3% { transform: rotate(0); }
  @for $i from 1 to $n {
    #{($i / $n) * 100 - 2}%,
    #{($i / $n) * 100 + 3}% { 
      transform: rotate(#{($i / $n) * -360}deg);
    }  
  }
  98%, 100% { transform: rotate(-360deg); }
}

Các khung hình chính gần như giống hệt nhau. Chúng tôi có các giá trị phần trăm giống nhau, cùng một vòng lặp và cùng một vòng quay.

Tại sao cả hai đều giống nhau? Bởi vì logic của họ là như nhau. Trong cả hai trường hợp, các hình ảnh được sắp xếp xung quanh một hình tròn và chúng ta cần xoay toàn bộ để hiển thị từng hình ảnh. Đó là cách tôi có thể sao chép các khung hình chính từ thanh trượt tròn và sử dụng cùng mã đó cho thanh trượt 3D của chúng tôi. Sự khác biệt duy nhất là chúng ta cần xoay container theo -90deg dọc theo trục x để xem hình ảnh vì chúng tôi đã xoay chúng theo 90deg trên cùng một trục. Sau đó, chúng tôi thêm một liên lạc của perspective để có được hiệu ứng 3D.

Đó là nó! Thanh trượt của chúng tôi đã hoàn thành. Đây là bản demo đầy đủ một lần nữa. Tất cả những gì bạn phải làm là thêm bao nhiêu hình ảnh tùy thích và cập nhật một biến để hoạt động.

Thanh trượt 3D dọc

Vì chúng tôi đang chơi trong không gian 3D, tại sao không tạo phiên bản dọc của thanh trượt trước đó? Cái cuối cùng quay dọc theo trục z, nhưng chúng ta cũng có thể di chuyển dọc theo trục x nếu muốn.

Nếu bạn so sánh mã cho cả hai phiên bản của thanh trượt này, bạn có thể không nhận ra ngay sự khác biệt vì nó chỉ có một ký tự! tôi đã thay thế rotate() với rotateX() bên trong khung hình chính và hình ảnh transform. Đó là nó!

Cần lưu ý rằng rotate() tương đương với rotateZ(), vì vậy bằng cách thay đổi trục từ Z đến X chúng tôi chuyển đổi thanh trượt từ phiên bản nằm ngang sang phiên bản dọc.

Thanh trượt khối

Chúng ta không thể nói về 3D trong CSS mà không có nói về hình khối. Và vâng, điều đó có nghĩa là chúng tôi sẽ tạo một phiên bản khác của thanh trượt.

Ý tưởng đằng sau phiên bản thanh trượt này là tạo ra một hình khối thực tế với các hình ảnh và xoay toàn bộ nội dung quanh một trục khác. Vì nó là một khối lập phương nên chúng ta đang xử lý sáu mặt. Chúng tôi sẽ sử dụng sáu hình ảnh, một hình ảnh cho mỗi mặt của khối lập phương. Vì vậy, không có Sass mà quay lại với vanilla CSS.

Hoạt hình đó là một chút áp đảo, phải không? Bạn thậm chí bắt đầu từ đâu?

Chúng ta có sáu mặt, vì vậy chúng ta cần thực hiện ít nhất sáu phép quay để mỗi hình có một lượt. Chà, thực ra, chúng ta cần năm phép quay - phép quay cuối cùng đưa chúng ta trở lại mặt hình ảnh đầu tiên. Nếu bạn lấy một khối Rubik — hoặc một số đồ vật có hình lập phương khác như xúc xắc — và xoay nó bằng tay, bạn sẽ biết rõ chúng ta đang làm gì.

.gallery {
  --s: 250px; /* the size */

  transform-style: preserve-3d;
  --_p: perspective(calc(2.5*var(--s)));
  animation: r 9s infinite cubic-bezier(.5, -0.5, .5, 1.5);
}

@keyframes r {
  0%, 3%   { transform: var(--_p); }
  14%, 19% { transform: var(--_p) rotateX(90deg); }
  31%, 36% { transform: var(--_p) rotateX(90deg) rotateZ(90deg); }
  47%, 52% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
  64%, 69% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg); }
  81%, 86% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg); }
  97%, 100%{ transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
}

Sản phẩm transform thuộc tính bắt đầu với các phép quay bằng XNUMX và trên mỗi trạng thái, chúng tôi nối thêm một phép quay mới trên một trục cụ thể cho đến khi chúng tôi đạt được sáu phép quay. Sau đó, chúng tôi trở lại hình ảnh đầu tiên.

Đừng quên vị trí của hình ảnh của chúng tôi. Mỗi cái được áp dụng cho một mặt của khối lập phương bằng cách sử dụng transform:

.gallery img {
  grid-area: 1 / 1;
  width: var(--s);
  aspect-ratio: 1;
  object-fit: cover;
  transform: var(--_t,) translateZ(calc(var(--s) / 2));
}
.gallery img:nth-child(2) { --_t: rotateX(-90deg); }
.gallery img:nth-child(3) { --_t: rotateY( 90deg) rotate(-90deg); }
.gallery img:nth-child(4) { --_t: rotateX(180deg) rotate( 90deg); }
.gallery img:nth-child(5) { --_t: rotateX( 90deg) rotate( 90deg); }
.gallery img:nth-child(6) { --_t: rotateY(-90deg); }

Có lẽ bạn đang nghĩ rằng có logic phức tạp kỳ lạ đằng sau những giá trị mà tôi đang sử dụng ở đó, phải không? Ồ không. Tất cả những gì tôi làm là mở DevTools và thử với các giá trị xoay khác nhau cho từng hình ảnh cho đến khi tôi hiểu đúng. Nghe có vẻ ngớ ngẩn, nhưng, này, nó hoạt động — đặc biệt là khi chúng tôi có một số lượng hình ảnh cố định và chúng tôi không tìm kiếm thứ gì đó hỗ trợ N hình ảnh.

Trên thực tế, hãy quên các giá trị tôi đang sử dụng và cố gắng tự mình thực hiện việc sắp xếp như một bài tập. Bắt đầu với tất cả các hình ảnh xếp chồng lên nhau, mở DevTools và bắt đầu! Bạn có thể sẽ kết thúc với mã khác và điều đó hoàn toàn ổn. Có thể có nhiều cách khác nhau để định vị hình ảnh.

mẹo với dấu phẩy bên trong là gì var()? Nó là một lỗi đánh máy?

Nó không phải là một lỗi đánh máy vì vậy đừng loại bỏ nó! Nếu bạn xóa nó, bạn sẽ nhận thấy rằng nó ảnh hưởng đến vị trí của hình ảnh đầu tiên. Bạn có thể thấy rằng trong mã của tôi, tôi đã xác định --_t cho tất cả các hình ảnh ngoại trừ hình ảnh đầu tiên vì tôi chỉ cần bản dịch cho nó. Dấu phẩy đó làm cho biến trở về giá trị null. Nếu không có dấu phẩy, chúng tôi sẽ không có dự phòng và toàn bộ giá trị sẽ không hợp lệ.

Từ các đặc điểm kỹ thuật:

Lưu ý: Đó là, var(--a,) là một chức năng hợp lệ, xác định rằng nếu --a thuộc tính tùy chỉnh không hợp lệ hoặc bị thiếu, var()` nên được thay thế bằng không có gì.

Thanh trượt khối ngẫu nhiên

Một chút ngẫu nhiên có thể là một cải tiến tốt đẹp cho loại hoạt hình này. Vì vậy, thay vì xoay khối lập phương theo thứ tự tuần tự, chúng ta có thể tung xúc xắc có thể nói như vậy và để khối lập phương lăn theo ý muốn.

Mát mẻ phải không? Tôi không biết về bạn, nhưng tôi thích phiên bản này hơn! Nó thú vị hơn và quá trình chuyển đổi khiến người xem hài lòng. Và đoán xem? Bạn có thể chơi với các giá trị để tạo thanh trượt khối ngẫu nhiên của riêng mình!

Logic thực sự không hề ngẫu nhiên - nó chỉ xuất hiện theo cách đó. Bạn xác định một transform trên mỗi khung hình chính cho phép bạn hiển thị một khuôn mặt và… thực sự là vậy! Bạn có thể chọn bất kỳ thứ tự nào bạn muốn.

@keyframes r {
  0%, 3%   { transform: var(--_p) rotate3d( 0, 0, 0,  0deg); }
  14%,19%  { transform: var(--_p) rotate3d(-1, 1, 0,180deg); }
  31%,36%  { transform: var(--_p) rotate3d( 0,-1, 0, 90deg); }
  47%,52%  { transform: var(--_p) rotate3d( 1, 0, 0, 90deg); }
  64%,69%  { transform: var(--_p) rotate3d( 1, 0, 0,-90deg); }
  81%,86%  { transform: var(--_p) rotate3d( 0, 1, 0, 90deg); }
  97%,100% { transform: var(--_p) rotate3d( 0, 0, 0,  0deg); }
}

Tôi đang sử dụng rotate3d() lần này nhưng tôi vẫn dựa vào DevTools để tìm các giá trị mà tôi cảm thấy “đúng”. Đừng cố tìm mối quan hệ giữa các khung hình chính vì đơn giản là không có mối quan hệ nào. Tôi đang xác định các biến đổi riêng biệt và sau đó xem kết quả “ngẫu nhiên”. Đảm bảo hình ảnh đầu tiên lần lượt là khung hình đầu tiên và khung hình cuối cùng, đồng thời hiển thị một hình ảnh khác trên mỗi khung hình khác.

Bạn không bắt buộc phải sử dụng một rotate3d() chuyển đổi như tôi đã làm. Bạn cũng có thể xâu chuỗi các phép quay khác nhau như chúng ta đã làm trong ví dụ trước. Chơi xung quanh và xem những gì bạn có thể nghĩ ra! Tôi sẽ chờ bạn chia sẻ phiên bản của bạn với tôi trong phần bình luận!

Kết thúc

Tôi hy vọng bạn thích loạt bài nhỏ này. Chúng tôi đã tạo một số thanh trượt thú vị (và hài hước) trong khi tìm hiểu rất nhiều về tất cả các loại khái niệm CSS trong suốt quá trình — từ vị trí lưới và thứ tự xếp chồng, đến độ trễ và chuyển đổi hoạt ảnh. Chúng tôi thậm chí phải chơi với một chút Sass để lặp qua một loạt các phần tử.

Và chúng tôi đã làm tất cả với cùng một HTML cho mỗi và mọi thanh trượt mà chúng tôi đã tạo. Làm thế nào là mát mẻ đó? CSS rất mạnh mẽ và có khả năng hoàn thành rất nhiều việc mà không cần sự trợ giúp của JavaScript.

Dấu thời gian:

Thêm từ Thủ thuật CSS