Tạo ảnh động cho các phần tử khi cuộn bằng ảnh động theo hướng cuộn

Tìm hiểu cách làm việc với Dòng thời gian cuộn và Dòng thời gian khung hiển thị để tạo ảnh động do cuộn theo cách khai báo.

Ngày phát hành: 5 tháng 5 năm 2023

Ảnh động do cuộn

Hỗ trợ trình duyệt

  • Chrome: 115.
  • Edge: 115.
  • Firefox: phía sau một cờ.
  • Safari: không được hỗ trợ.

Nguồn

Ảnh động do cuộn điều khiển là một mẫu trải nghiệm người dùng phổ biến trên web. Ảnh động do cuộn điều khiển được liên kết với vị trí cuộn của vùng chứa cuộn. Điều này có nghĩa là khi bạn cuộn lên hoặc xuống, ảnh động được liên kết sẽ tua đi hoặc tua lại để phản hồi trực tiếp. Ví dụ: các hiệu ứng như hình nền có hiệu ứng thị sai hoặc chỉ báo đọc di chuyển khi bạn cuộn.

Chỉ báo đọc trên một tài liệu, được điều khiển bằng thao tác cuộn.

Một loại ảnh động tương tự do cuộn là ảnh động được liên kết với vị trí của một phần tử trong vùng chứa cuộn. Ví dụ: với tính năng này, các phần tử có thể mờ dần khi xuất hiện trong khung hiển thị.

Các hình ảnh trên trang này sẽ mờ dần khi xuất hiện.

Cách cổ điển để đạt được những hiệu ứng này là phản hồi các sự kiện cuộn trên luồng chính, dẫn đến hai vấn đề chính:

  • Các trình duyệt hiện đại thực hiện thao tác cuộn trên một quy trình riêng biệt và do đó phân phối các sự kiện cuộn không đồng bộ.
  • Ảnh động trong luồng chính có thể bị giật.

Điều này khiến việc tạo ảnh động hiệu suất cao do cuộn điều khiển và đồng bộ với thao tác cuộn trở nên không thể hoặc rất khó.

Từ Chrome phiên bản 115, bạn có thể sử dụng một bộ API và khái niệm mới để bật ảnh động do cuộn khai báo: Dòng thời gian cuộn và Dòng thời gian xem.

Các khái niệm mới này tích hợp với Web Animations API (WAAPI)CSS Animations API hiện có, cho phép kế thừa các lợi thế mà các API hiện có này mang lại. Điều này bao gồm cả khả năng chạy ảnh động do cuộn điều khiển trên luồng chính. Đúng vậy, bạn đã đọc đúng: giờ đây, bạn có thể có ảnh động mượt mà, do thao tác cuộn điều khiển, chạy trên luồng chính, chỉ với vài dòng mã bổ sung. Còn gì tuyệt hơn thế nữa!

Ảnh động trên web, một bản tóm tắt nhỏ

Ảnh động trên web bằng CSS

Để tạo ảnh động trong CSS, hãy xác định một tập hợp khung hình chính bằng cách sử dụng quy tắc tại @keyframes. Liên kết ảnh động với một phần tử bằng thuộc tính animation-name, đồng thời đặt animation-duration để xác định thời lượng của ảnh động. Có nhiều thuộc tính viết tay animation-* khác –animation-easing-functionanimation-fill-mode chỉ là một vài ví dụ – tất cả đều có thể được kết hợp trong viết tắt animation.

Ví dụ: sau đây là ảnh động tăng tỷ lệ một phần tử trên trục X trong khi cũng thay đổi màu nền của phần tử đó:

@keyframes scale-up {
  from {
    background-color: red;
    transform: scaleX(0);
  }
  to {
    background-color: darkred;
    transform: scaleX(1);
  }
}

#progressbar {
  animation: 2.5s linear forwards scale-up;
}

Ảnh động trên web bằng JavaScript

Trong JavaScript, bạn có thể sử dụng API Ảnh động trên web để đạt được kết quả tương tự. Bạn có thể thực hiện việc này bằng cách tạo các thực thể AnimationKeyFrameEffect mới hoặc sử dụng phương thức Element animate() ngắn hơn nhiều.

document.querySelector('#progressbar').animate(
  {
    backgroundColor: ['red', 'darkred'],
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    duration: 2500,
    fill: 'forwards',
    easing: 'linear',
   }
);

Kết quả hình ảnh của đoạn mã JavaScript ở trên giống hệt với phiên bản CSS trước đó.

Tiến trình ảnh động

Theo mặc định, ảnh động đính kèm vào một phần tử sẽ chạy trên dòng thời gian của tài liệu. Thời gian gốc bắt đầu từ 0 khi trang tải và bắt đầu tích tắc khi thời gian đồng hồ trôi qua. Đây là dòng thời gian ảnh động mặc định và cho đến nay, đây là dòng thời gian ảnh động duy nhất mà bạn có quyền truy cập.

Quy cách ảnh động do cuộn điều khiển xác định hai loại tiến trình mới mà bạn có thể sử dụng:

  • Dòng thời gian tiến trình cuộn: một dòng thời gian được liên kết với vị trí cuộn của vùng chứa cuộn dọc theo một trục cụ thể.
  • Dòng thời gian tiến trình xem: một dòng thời gian được liên kết với vị trí tương đối của một phần tử cụ thể trong vùng chứa cuộn.

Dòng thời gian tiến trình cuộn

Dòng thời gian tiến trình cuộn là dòng thời gian ảnh động được liên kết với tiến trình ở vị trí cuộn của vùng chứa cuộn (còn gọi là scrollport hoặc scroller) dọc theo một trục cụ thể. Hàm này chuyển đổi một vị trí trong phạm vi cuộn thành tỷ lệ phần trăm tiến trình.

Vị trí cuộn bắt đầu thể hiện tiến trình 0% và vị trí cuộn kết thúc thể hiện tiến trình 100%. Trong hình ảnh trực quan sau, bạn có thể thấy tiến trình tăng từ 0% đến 100% khi bạn cuộn thanh cuộn từ trên xuống dưới.

Hình ảnh trực quan về Dòng thời gian tiến trình cuộn. Khi bạn di chuyển xuống cuối thanh cuộn, giá trị tiến trình sẽ tăng từ 0% đến 100%.

✨ Hãy tự mình dùng thử

Dòng thời gian tiến trình cuộn thường được viết tắt thành "Dòng thời gian cuộn".

Xem tiến trình theo dòng thời gian

Loại tiến trình này được liên kết với tiến trình tương đối của một phần tử cụ thể trong vùng chứa cuộn. Giống như Tiến trình cuộn, độ dời cuộn của thanh cuộn sẽ được theo dõi. Không giống như Tiến trình cuộn theo dòng thời gian, tiến trình được xác định bằng vị trí tương đối của đối tượng trong thanh cuộn đó.

Điều này tương đương với cách hoạt động của IntersectionObserver, có thể theo dõi mức độ hiển thị của một phần tử trong thanh cuộn. Nếu phần tử không hiển thị trong thanh cuộn, thì phần tử đó không giao nhau. Nếu bạn có thể nhìn thấy phần lồng ghép bên trong thanh cuộn – ngay cả phần nhỏ nhất – thì đó là phần lồng ghép giao nhau.

Dòng thời gian tiến trình xem bắt đầu từ thời điểm đối tượng bắt đầu giao nhau với thanh cuộn và kết thúc khi đối tượng ngừng giao nhau với thanh cuộn. Trong hình ảnh trực quan sau, bạn có thể thấy tiến trình bắt đầu đếm từ 0% khi đối tượng vào vùng chứa cuộn và đạt đến 100% ngay tại thời điểm đối tượng rời khỏi vùng chứa cuộn.

Hình ảnh trực quan của Dòng thời gian tiến trình xem. Tiến trình sẽ tăng từ 0% đến 100% khi chủ thể (hộp màu xanh lục) vượt qua thanh cuộn.

✨ Hãy tự mình dùng thử

Dòng thời gian tiến trình xem thường được viết tắt thành "Dòng thời gian xem". Bạn có thể nhắm đến các phần cụ thể của Dòng thời gian xem dựa trên kích thước của đối tượng, nhưng chúng ta sẽ nói về điều này sau.

Thực hành với Dòng thời gian tiến trình cuộn

Tạo Dòng thời gian tiến trình cuộn ẩn danh trong CSS

Cách dễ nhất để tạo Dòng thời gian cuộn trong CSS là sử dụng hàm scroll(). Thao tác này sẽ tạo một Dòng thời gian cuộn ẩn danh mà bạn có thể đặt làm giá trị cho thuộc tính animation-timeline mới.

Ví dụ:

@keyframes animate-it { … }

.subject {
  animation: animate-it linear;
  animation-timeline: scroll(root block);
}

Hàm scroll() chấp nhận đối số <scroller><axis>.

Sau đây là các giá trị được chấp nhận cho đối số <scroller>:

  • nearest: Sử dụng vùng chứa cuộn gốc gần nhất (mặc định).
  • root: Sử dụng khung nhìn tài liệu làm vùng chứa cuộn.
  • self: Sử dụng chính phần tử đó làm vùng chứa cuộn.

Sau đây là các giá trị được chấp nhận cho đối số <axis>:

  • block: Sử dụng thước đo tiến trình dọc theo trục khối của vùng chứa cuộn (mặc định).
  • inline: Sử dụng thước đo tiến trình dọc theo trục nội tuyến của vùng chứa cuộn.
  • y: Sử dụng thông tin đo lường tiến trình dọc theo trục y của vùng chứa cuộn.
  • x: Sử dụng thước đo tiến trình dọc theo trục x của vùng chứa cuộn.

Ví dụ: để liên kết ảnh động với thanh cuộn gốc trên trục khối, các giá trị cần truyền vào scroll()rootblock. Tổng hợp lại, giá trị là scroll(root block).

Bản minh hoạ: Chỉ báo tiến trình đọc

Bản minh hoạ này có chỉ báo tiến trình đọc được cố định ở đầu khung nhìn. Khi bạn cuộn xuống trang, thanh tiến trình sẽ tăng lên cho đến khi chiếm toàn bộ chiều rộng khung nhìn khi đến cuối tài liệu. Dòng thời gian tiến trình cuộn ẩn danh được dùng để điều khiển ảnh động.

Bản minh hoạ: Chỉ báo tiến trình đọc.

✨ Hãy tự mình dùng thử

Chỉ báo tiến trình đọc được đặt ở đầu trang bằng cách sử dụng vị trí cố định. Để tận dụng ảnh động kết hợp, không phải width đang được tạo ảnh động mà phần tử này được điều chỉnh theo tỷ lệ trên trục x bằng transform.

<body>
  <div id="progress"></div>
  …
</body>
@keyframes grow-progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

#progress {
  position: fixed;
  left: 0; top: 0;
  width: 100%; height: 1em;
  background: red;

  transform-origin: 0 50%;
  animation: grow-progress auto linear;
  animation-timeline: scroll();
}

Dòng thời gian cho ảnh động grow-progress trên phần tử #progress được đặt thành dòng thời gian ẩn danh được tạo bằng scroll(). Không có đối số nào được cung cấp cho scroll(), vì vậy, hàm này sẽ quay lại sử dụng các giá trị mặc định.

Thanh cuộn mặc định để theo dõi là thanh cuộn nearest và trục mặc định là block. Điều này giúp nhắm mục tiêu hiệu quả đến thanh cuộn gốc vì đó là thanh cuộn gần nhất của phần tử #progress, đồng thời theo dõi hướng khối của thanh cuộn đó.

Tạo Dòng thời gian tiến trình cuộn có tên trong CSS

Một cách khác để xác định Tiến trình cuộn là sử dụng tiến trình có tên. Cách này dài dòng hơn một chút, nhưng có thể hữu ích khi bạn không nhắm đến thanh cuộn mẹ hoặc thanh cuộn gốc, hoặc khi trang sử dụng nhiều tiến trình hoặc khi tính năng tra cứu tự động không hoạt động. Bằng cách này, bạn có thể xác định Dòng thời gian tiến trình cuộn theo tên mà bạn đặt.

Để tạo Dòng thời gian tiến trình cuộn có tên trên một phần tử, hãy đặt thuộc tính CSS scroll-timeline-name trên vùng chứa cuộn thành một giá trị nhận dạng mà bạn muốn. Giá trị phải bắt đầu bằng --.

Để điều chỉnh trục cần theo dõi, hãy khai báo thuộc tính scroll-timeline-axis. Giá trị được phép giống với đối số <axis> của scroll().

Cuối cùng, để liên kết ảnh động với Tiến trình cuộn, hãy đặt thuộc tính animation-timeline trên phần tử cần tạo ảnh động thành cùng giá trị với giá trị nhận dạng được dùng cho scroll-timeline-name.

Ví dụ về mã:

@keyframes animate-it { … }

.scroller {
  scroll-timeline-name: --my-scroller;
  scroll-timeline-axis: inline;
}

.scroller .subject {
  animation: animate-it linear;
  animation-timeline: --my-scroller;
}

Nếu muốn, bạn có thể kết hợp scroll-timeline-namescroll-timeline-axis trong viết tắt scroll-timeline. Ví dụ:

scroll-timeline: --my-scroller inline;

Bản minh hoạ này có một chỉ báo bước xuất hiện phía trên mỗi băng chuyền hình ảnh. Khi băng chuyền chứa 3 hình ảnh, thanh chỉ báo sẽ bắt đầu ở chiều rộng 33% để cho biết bạn đang xem hình ảnh thứ nhất trong số 3 hình ảnh. Khi hình ảnh cuối cùng xuất hiện trong khung hiển thị (do thanh cuộn đã cuộn đến cuối), chỉ báo sẽ chiếm toàn bộ chiều rộng của thanh cuộn. Dòng thời gian tiến trình cuộn có tên được dùng để điều khiển ảnh động.

Minh hoạ: Chỉ báo bước băng chuyền ngang.

✨ Hãy tự mình dùng thử

Mã đánh dấu cơ sở cho một thư viện như sau:

<div class="gallery" style="--num-images: 2;">
  <div class="gallery__scrollcontainer">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">…</div>
    <div class="gallery__entry">…</div>
  </div>
</div>

Phần tử .gallery__progress được đặt vị trí tuyệt đối trong phần tử bao bọc .gallery. Kích thước ban đầu của nó được xác định bằng thuộc tính tuỳ chỉnh --num-images.

.gallery {
  position: relative;
}


.gallery__progress {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 1em;
  transform: scaleX(calc(1 / var(--num-images)));
}

.gallery__scrollcontainer bố trí các phần tử .gallery__entry được chứa theo chiều ngang và là phần tử cuộn. Bằng cách theo dõi vị trí cuộn, .gallery__progress sẽ được tạo ảnh động. Bạn có thể thực hiện việc này bằng cách tham chiếu đến Dòng thời gian tiến trình cuộn có tên --gallery__scrollcontainer.

@keyframes grow-progress {
  to { transform: scaleX(1); }
}

.gallery__scrollcontainer {
  overflow-x: scroll;
  scroll-timeline: --gallery__scrollcontainer inline;
}
.gallery__progress {
  animation: auto grow-progress linear forwards;
  animation-timeline: --gallery__scrollcontainer;
}

Tạo tiến trình cuộn bằng JavaScript

Để tạo Dòng thời gian cuộn trong JavaScript, hãy tạo một thực thể mới của lớp ScrollTimeline. Truyền vào một túi thuộc tính có sourceaxis mà bạn muốn theo dõi.

  • source: Tham chiếu đến phần tử có thanh cuộn mà bạn muốn theo dõi. Sử dụng document.documentElement để nhắm đến thanh cuộn gốc.
  • axis: Xác định trục cần theo dõi. Tương tự như biến thể CSS, các giá trị được chấp nhận là block, inline, xy.
const tl = new ScrollTimeline({
  source: document.documentElement,
});

Để đính kèm ảnh động vào Ảnh động trên web, hãy truyền ảnh động đó dưới dạng thuộc tính timeline và bỏ qua mọi duration nếu có.

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
});

Bản minh hoạ: Xem lại chỉ báo tiến trình đọc

Để tạo lại chỉ báo tiến trình đọc bằng JavaScript, trong khi vẫn sử dụng cùng một mã đánh dấu, hãy sử dụng mã JavaScript sau:

const $progressbar = document.querySelector('#progress');

$progressbar.style.transformOrigin = '0% 50%';
$progressbar.animate(
  {
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    fill: 'forwards',
    timeline: new ScrollTimeline({
      source: document.documentElement,
    }),
  }
);

Kết quả hình ảnh giống hệt trong phiên bản CSS: timeline được tạo theo dõi thanh cuộn gốc và điều chỉnh tỷ lệ #progress trên trục x từ 0% đến 100% khi bạn cuộn trang.

✨ Hãy tự mình dùng thử

Thực hành với Dòng thời gian tiến trình xem

Tạo Dòng thời gian tiến trình xem ẩn danh trong CSS

Để tạo Dòng thời gian tiến trình xem, hãy sử dụng hàm view(). Các đối số được chấp nhận là <axis><view-timeline-inset>.

  • <axis> giống với tiến trình cuộn trên Dòng thời gian và xác định trục cần theo dõi. Giá trị mặc định là block.
  • Với <view-timeline-inset>, bạn có thể chỉ định một độ dời (dương hoặc âm) để điều chỉnh các giới hạn khi một phần tử được coi là có trong khung hiển thị hay không. Giá trị phải là phần trăm hoặc auto, trong đó auto là giá trị mặc định.

Ví dụ: để liên kết ảnh động với một phần tử giao nhau với thanh cuộn trên trục khối, hãy sử dụng view(block). Tương tự như scroll(), hãy đặt giá trị này cho thuộc tính animation-timeline và đừng quên đặt animation-duration thành auto.

Khi sử dụng mã sau, mọi img sẽ mờ dần khi nó đi qua khung nhìn trong khi bạn cuộn.

@keyframes reveal {
  from { opacity: 0; }
  to { opacity: 1; }
}

img {
  animation: reveal linear;
  animation-timeline: view();
}

Phần mở đầu: Xem các phạm vi Dòng thời gian

Theo mặc định, ảnh động được liên kết với Dòng thời gian của thành phần hiển thị sẽ đính kèm vào toàn bộ phạm vi dòng thời gian. Quá trình này bắt đầu từ thời điểm đối tượng sắp vào cuộn và kết thúc khi đối tượng đã rời khỏi cuộn hoàn toàn.

Bạn cũng có thể liên kết đến một phần cụ thể của Dòng thời gian của chế độ xem bằng cách chỉ định phạm vi mà phần đó sẽ đính kèm. Ví dụ: điều này chỉ xảy ra khi đối tượng đang đi vào thanh cuộn. Trong hình ảnh trực quan sau đây, tiến trình bắt đầu đếm từ 0% khi đối tượng vào vùng chứa cuộn nhưng đã đạt 100% từ thời điểm đối tượng hoàn toàn giao nhau.

Dòng thời gian của chế độ xem được đặt để theo dõi phạm vi mục nhập của chủ đề. Ảnh động chỉ chạy khi đối tượng đang đi vào cuộn.

Sau đây là các phạm vi Dòng thời gian của chế độ xem mà bạn có thể nhắm đến:

  • cover: Biểu thị toàn bộ phạm vi tiến trình xem.
  • entry: Biểu thị phạm vi trong đó hộp chính đang chuyển vào phạm vi hiển thị tiến trình xem.
  • exit: Biểu thị phạm vi trong đó hộp chính đang thoát khỏi phạm vi hiển thị tiến trình xem.
  • entry-crossing: Biểu thị phạm vi trong đó hộp chính vượt qua cạnh đường viền cuối.
  • exit-crossing: Biểu thị phạm vi trong đó hộp chính vượt qua cạnh đường viền bắt đầu.
  • contain: Biểu thị phạm vi trong đó hộp chính được chứa hoàn toàn hoặc bao phủ hoàn toàn phạm vi hiển thị tiến trình xem trong cổng cuộn. Điều này tuỳ thuộc vào việc đối tượng cao hơn hay thấp hơn thanh cuộn.

Để xác định một phạm vi, bạn phải đặt phạm vi bắt đầu và phạm vi kết thúc. Mỗi hàm này bao gồm tên-dải-ô (xem danh sách ở trên) và độ dời-dải-ô để xác định vị trí trong tên-dải-ô đó. Độ lệch phạm vi thường là một tỷ lệ phần trăm trong khoảng từ 0% đến 100%, nhưng bạn cũng có thể chỉ định một độ dài cố định như 20em.

Ví dụ: nếu bạn muốn chạy ảnh động từ thời điểm đối tượng xuất hiện, hãy chọn entry 0% làm điểm bắt đầu phạm vi. Để hoàn tất việc này trước khi chủ đề được nhập, hãy chọn entry 100% làm giá trị cho phạm vi kết thúc.

Trong CSS, bạn đặt thuộc tính này bằng thuộc tính animation-range. Ví dụ:

animation-range: entry 0% entry 100%;

Trong JavaScript, hãy sử dụng các thuộc tính rangeStartrangeEnd.

$el.animate(
  keyframes,
  {
    timeline: tl,
    rangeStart: 'entry 0%',
    rangeEnd: 'entry 100%',
  }
);

Sử dụng công cụ được nhúng bên dưới để xem mỗi tên dải ô đại diện cho gì và tỷ lệ phần trăm ảnh hưởng như thế nào đến vị trí bắt đầu và kết thúc. Hãy thử đặt range-start thành entry 0% và range-end thành cover 50%, sau đó kéo thanh cuộn để xem kết quả ảnh động.

Trình trực quan hoá phạm vi Dòng thời gian của Chế độ xem, có tại https://goo.gle/view-timeline-range-tool

Xem bản ghi âm

Như bạn có thể nhận thấy khi sử dụng công cụ Phạm vi tiến trình xem này, một số phạm vi có thể được nhắm mục tiêu bằng hai tổ hợp tên-phạm-vi + độ-dời-phạm-vi khác nhau. Ví dụ: entry 0%, entry-crossing 0%cover 0% đều nhắm đến cùng một khu vực.

Khi range-start và range-end nhắm đến cùng một range-name và trải dài trên toàn bộ phạm vi – từ 0% đến 100%– bạn có thể rút ngắn giá trị thành chỉ tên phạm vi. Ví dụ: animation-range: entry 0% entry 100%; có thể được viết lại thành animation-range: entry ngắn hơn nhiều.

Bản minh hoạ: Hiệu ứng hiển thị hình ảnh

Bản minh hoạ này làm mờ hình ảnh khi hình ảnh đó vào cổng cuộn. Bạn có thể thực hiện việc này bằng cách sử dụng Dòng thời gian của lượt xem ẩn danh. Phạm vi ảnh động đã được điều chỉnh để mỗi hình ảnh có độ mờ đầy đủ khi ở giữa thanh cuộn.

Bản minh hoạ: Hiện hình ảnh

✨ Hãy tự mình dùng thử

Hiệu ứng mở rộng được thực hiện bằng cách sử dụng một clip-path có ảnh động. CSS dùng cho hiệu ứng này như sau:

@keyframes reveal {
  from { opacity: 0; clip-path: inset(0% 60% 0% 50%); }
  to { opacity: 1; clip-path: inset(0% 0% 0% 0%); }
}

.revealing-image {
  animation: auto linear reveal both;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

Tạo Dòng thời gian tiến trình xem có tên trong CSS

Tương tự như cách Dòng thời gian cuộn có các phiên bản được đặt tên, bạn cũng có thể tạo Dòng thời gian thành phần hiển thị được đặt tên. Thay vì các thuộc tính scroll-timeline-*, bạn sử dụng các biến thể có tiền tố view-timeline-, cụ thể là view-timeline-nameview-timeline-axis.

Bạn cũng áp dụng cùng một loại giá trị và cùng một quy tắc để tra cứu dòng thời gian được đặt tên.

Bản minh hoạ: Xem lại tính năng hiển thị hình ảnh

Làm lại bản minh hoạ hiển thị hình ảnh trước đó, mã sửa đổi sẽ có dạng như sau:

.revealing-image {
  view-timeline-name: --revealing-image;
  view-timeline-axis: block;

  animation: auto linear reveal both;
  animation-timeline: --revealing-image;
  animation-range: entry 25% cover 50%;
}

Khi sử dụng view-timeline-name: revealing-image, phần tử sẽ được theo dõi trong thanh cuộn gần nhất. Sau đó, cùng một giá trị này được dùng làm giá trị cho thuộc tính animation-timeline. Kết quả hình ảnh vẫn giống như trước.

✨ Hãy tự mình dùng thử

Tạo Dòng thời gian tiến trình xem trong JavaScript

Để tạo Dòng thời gian của thành phần hiển thị trong JavaScript, hãy tạo một thực thể mới của lớp ViewTimeline. Truyền vào một túi thuộc tính có subject mà bạn muốn theo dõi, axisinset.

  • subject: Tham chiếu đến phần tử mà bạn muốn theo dõi trong thanh cuộn riêng của phần tử đó.
  • axis: Trục cần theo dõi. Tương tự như biến thể CSS, các giá trị được chấp nhận là block, inline, xy.
  • inset: Điều chỉnh phần lồng ghép (dương) hoặc phần lồng ghép ngoài (âm) của cuộn khi xác định xem hộp có trong chế độ xem hay không.
const tl = new ViewTimeline({
  subject: document.getElementById('subject'),
});

Để đính kèm ảnh động vào Ảnh động trên web, hãy truyền ảnh động đó dưới dạng thuộc tính timeline và bỏ qua mọi duration nếu có. Bạn có thể truyền thông tin phạm vi bằng cách sử dụng các thuộc tính rangeStartrangeEnd.

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
  rangeStart: 'entry 25%',
  rangeEnd: 'cover 50%',
});

✨ Hãy tự mình dùng thử

Những tính năng khác bạn có thể thử

Đính kèm vào nhiều phạm vi Dòng thời gian của thành phần hiển thị bằng một nhóm khung hình chính

Hãy xem bản minh hoạ danh sách liên hệ này, trong đó các mục trong danh sách đều có ảnh động. Khi một mục danh sách đi vào cổng cuộn từ dưới cùng, mục đó sẽ trượt và mờ dần vào, và khi mục đó thoát khỏi cổng cuộn ở trên cùng, mục đó sẽ trượt và mờ dần ra.

Bản minh hoạ: Danh bạ

✨ Hãy tự mình dùng thử

Đối với bản minh hoạ này, mỗi phần tử được trang trí bằng một Dòng thời gian khung hiển thị theo dõi phần tử khi phần tử đó vượt qua vùng cuộn, nhưng hai ảnh động do cuộn điều khiển được đính kèm vào phần tử đó. Ảnh động animate-in được đính kèm vào dải ô entry của dòng thời gian và ảnh động animate-out được đính kèm vào dải ô exit của dòng thời gian.

@keyframes animate-in {
  0% { opacity: 0; transform: translateY(100%); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes animate-out {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-100%); }
}

#list-view li {
  animation: animate-in linear forwards,
             animate-out linear forwards;
  animation-timeline: view();
  animation-range: entry, exit;
}

Thay vì chạy hai ảnh động khác nhau được đính kèm vào hai phạm vi khác nhau, bạn cũng có thể tạo một nhóm khung hình chính đã chứa thông tin về phạm vi.

@keyframes animate-in-and-out {
  entry 0%  {
    opacity: 0; transform: translateY(100%);
  }
  entry 100%  {
    opacity: 1; transform: translateY(0);
  }
  exit 0% {
    opacity: 1; transform: translateY(0);
  }
  exit 100% {
    opacity: 0; transform: translateY(-100%);
  }
}

#list-view li {
  animation: linear animate-in-and-out;
  animation-timeline: view();
}

Vì các khung hình chính chứa thông tin về phạm vi, nên bạn không cần chỉ định animation-range. Kết quả vẫn giống như trước.

✨ Hãy tự mình dùng thử

Đính kèm vào Dòng thời gian cuộn không phải là thành phần cấp trên

Cơ chế tra cứu cho Dòng thời gian cuộn và Dòng thời gian thành phần hiển thị được đặt tên chỉ giới hạn ở các thành phần hiển thị gốc. Tuy nhiên, rất thường thì phần tử cần tạo ảnh động không phải là phần tử con của thanh cuộn cần được theo dõi.

Để thực hiện việc này, thuộc tính timeline-scope sẽ phát huy tác dụng. Bạn sử dụng thuộc tính này để khai báo một tiến trình có tên đó mà không cần thực sự tạo tiến trình đó. Điều này giúp dòng thời gian có tên đó có phạm vi rộng hơn. Trong thực tế, bạn sử dụng thuộc tính timeline-scope trên một phần tử mẹ dùng chung để dòng thời gian của thanh cuộn con có thể đính kèm vào phần tử đó.

Ví dụ:

.parent {
  timeline-scope: --tl;
}
.parent .scroller {
  scroll-timeline: --tl;
}
.parent .scroller ~ .subject {
  animation: animate linear;
  animation-timeline: --tl;
}

Trong đoạn mã này:

  • Phần tử .parent khai báo một tiến trình có tên --tl. Mọi thành phần con của nó đều có thể tìm thấy và sử dụng thuộc tính này làm giá trị cho thuộc tính animation-timeline.
  • Phần tử .scroller thực sự xác định một Dòng thời gian cuộn có tên --tl. Theo mặc định, chỉ các phần tử con mới nhìn thấy phần tử này, nhưng vì .parent đã đặt phần tử này làm scroll-timeline-root, nên phần tử này sẽ đính kèm vào phần tử đó.
  • Phần tử .subject sử dụng dòng thời gian --tl. Phương thức này sẽ đi lên cây tổ tiên và tìm thấy --tl trên .parent. Với --tl trên .parent trỏ đến --tl của .scroller, về cơ bản, .subject sẽ theo dõi Dòng thời gian tiến trình cuộn của .scroller.

Nói cách khác, bạn có thể sử dụng timeline-root để di chuyển một tiến trình lên một thành phần cấp trên (còn gọi là chuyển lên trên) để tất cả thành phần con của thành phần cấp trên đó có thể truy cập vào tiến trình đó.

Bạn có thể sử dụng thuộc tính timeline-scope với cả Dòng thời gian cuộn và Dòng thời gian xem.

Các bản minh hoạ và tài nguyên khác

Tất cả các bản minh hoạ được đề cập trong bài viết này trên trang web thu nhỏ scroll-driven-animations.style. Trang web này có nhiều bản minh hoạ khác để làm nổi bật những gì có thể làm được với ảnh động do Cuộn điều khiển.

Một trong những bản minh hoạ bổ sung là danh sách ảnh bìa đĩa nhạc này. Mỗi ảnh bìa xoay theo hình 3D khi được đặt ở vị trí trung tâm.

Bản minh hoạ: Cover Flow

✨ Hãy tự mình dùng thử

Hoặc bản minh hoạ xếp chồng thẻ này tận dụng position: sticky. Khi các thẻ xếp chồng lên nhau, các thẻ đã bị kẹt sẽ thu nhỏ, tạo ra hiệu ứng chiều sâu đẹp mắt. Cuối cùng, toàn bộ ngăn xếp sẽ trượt ra khỏi khung hiển thị dưới dạng một nhóm.

Bản minh hoạ: Xếp chồng thẻ.

✨ Hãy tự mình dùng thử

Cũng có trên scroll-driven-animations.style là một tập hợp các công cụ như hình ảnh trực quan về Tiến trình phạm vi tiến trình xem đã có trong bài đăng này.

Hoạt ảnh do cuộn cũng được đề cập trong phần Tính năng mới trong Hoạt ảnh trên web tại Google I/O 2023.