Kiểm soát chặt chẽ các phép biến đổi CSS bằng các thuộc tính biến đổi riêng lẻ

Biến đổi các phần tử bằng các thuộc tính translate, rotatescale

Thuộc tính CSS transform

Để áp dụng hành động chuyển đổi cho một phần tử, hãy sử dụng Thuộc tính CSS transform. Cơ sở lưu trú chấp nhận một hoặc nhiều <transform-function>, được áp dụng lần lượt.

.target {
  transform: translateX(50%) rotate(30deg) scale(1.2);
}

Phần tử được nhắm mục tiêu được chuyển đổi trên trục X 50%, xoay 30 độ và cuối cùng tăng tỷ lệ lên 120%.

Mặc dù thuộc tính transform hoạt động rất hiệu quả, nhưng sẽ hơi tẻ nhạt khi bạn muốn thay đổi từng giá trị trong số đó.

Để thay đổi tỷ lệ khi di chuột, bạn phải sao chép tất cả các hàm trong thuộc tính biến đổi, mặc dù các giá trị của chúng vẫn không thay đổi.

.target:hover {
  transform: translateX(50%) rotate(30deg) scale(2); /* Only the value of scale() changed */
}

Các thuộc tính biến đổi riêng lẻ

Thông tin vận chuyển bằng Chrome 104 là các thuộc tính riêng để chuyển đổi CSS. Các thuộc tính là scale, rotatetranslate mà bạn có thể dùng để xác định riêng từng phần của phép biến đổi.

Bằng cách làm như vậy, Chrome sẽ kết hợp với Firefox và Safari đã hỗ trợ các thuộc tính này.

Hỗ trợ trình duyệt

  • 104
  • 104
  • 72
  • 14,1

Nguồn

Bằng cách viết lại ví dụ transform trước đó với các thuộc tính riêng lẻ, đoạn mã của bạn sẽ trở thành như sau:

.target {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

Các vấn đề về đơn đặt hàng

Một điểm khác biệt chính giữa thuộc tính transform gốc của CSS và các thuộc tính mới là thứ tự áp dụng các hành động biến đổi đã khai báo.

Với transform, các hàm biến đổi được áp dụng theo thứ tự viết từ trái (bên ngoài) sang phải (bên trong).

Với các thuộc tính biến đổi riêng lẻ, thứ tự không phải là thứ tự mà các thuộc tính đó được khai báo. Thứ tự luôn giống nhau: đầu tiên là translate (bên ngoài), sau đó là rotate và sau đó là scale (bên trong).

Điều đó có nghĩa là cả hai đoạn mã sau đây đều cung cấp cùng một kết quả:

.transform--individual {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

.transform--individual-alt {
  rotate: 30deg;
  translate: 50% 0;
  scale: 1.2;
}

Trong cả hai trường hợp, trước tiên, các phần tử được nhắm mục tiêu sẽ được 50% dịch trên trục X, sau đó được xoay theo 30deg và cuối cùng sẽ được điều chỉnh theo tỷ lệ 1.2.

Nếu một trong các thuộc tính biến đổi riêng lẻ được khai báo cùng với thuộc tính transform, thì các phép biến đổi riêng lẻ sẽ được áp dụng đầu tiên (translate, rotate và sau đó là scale) với transform cuối cùng (bên trong). Bạn có thể xem thêm thông tin chi tiết trong quy cách xác định cách tính ma trận biến đổi.

Hoạt ảnh

Lý do chính khiến các thuộc tính này được thêm vào là để tạo ảnh động dễ dàng hơn. Giả sử bạn muốn tạo ảnh động cho một phần tử như sau:

Biểu đồ khung hình chính.

Sử dụng transform

Để triển khai ảnh động này bằng transform, bạn phải tính toán tất cả các giá trị giữa cho mọi phép biến đổi đã xác định và đưa các giá trị đó vào mỗi khung hình chính. Ví dụ: để thực hiện xoay vòng ở mức 10%, bạn cũng phải tính toán giá trị của các phép biến đổi khác vì thuộc tính transform cần tất cả giá trị đó.

Biểu đồ khung chính có tính toán các giá trị trung gian.

Mã CSS thu được sẽ có dạng như sau:

@keyframes anim {
  0% { transform: translateX(0%); }
  5% { transform: translateX(5%) rotate(90deg) scale(1.2); }
  10% { transform: translateX(10%) rotate(180deg) scale(1.2); }
  90% { transform: translateX(90%) rotate(180deg) scale(1.2); }
  95% { transform: translateX(95%) rotate(270deg) scale(1.2); }
  100% { transform: translateX(100%) rotate(360deg); }
}

.target {
  animation: anim 2s;
  animation-fill-mode: forwards;
}

Sử dụng các thuộc tính biến đổi riêng lẻ

Với các thuộc tính biến đổi riêng lẻ, việc viết các thuộc tính này trở nên dễ dàng hơn nhiều. Thay vì kéo tất cả các phép biến đổi từ khung hình chính vào khung hình chính, bạn có thể nhắm mục tiêu từng phép biến đổi. Bạn cũng không cần phải tính toán tất cả các giá trị ở giữa đó nữa.

@keyframes anim {
  0% { translate: 0% 0; }
  100% { translate: 100% 0; }

  0%, 100% { scale: 1; }
  5%, 95% { scale: 1.2; }

  0% { rotate: 0deg; }
  10%, 90% { rotate: 180deg; }
  100% { rotate: 360deg; }
}

.target {
  animation: anim 2s;
  animation-fill-mode: forwards;
}

Sử dụng các thuộc tính biến đổi riêng lẻ và một số khung hình chính

Để tạo mã theo mô-đun, bạn có thể chia mỗi ảnh động phụ thành một nhóm khung hình chính riêng.

@keyframes move {
  0% { translate: 0% 0; }
  100% { translate: 100% 0; }
}

@keyframes scale {
  0%, 100% { scale: 1; }
  5%, 95% { scale: 1.2; }
}

@keyframes rotate {
  0% { rotate: 0deg; }
  10%, 90% { rotate: 180deg; }
  100% { rotate: 360deg; }
}

.target {
  animation: move 2s, scale 2s, rotate 2s;
  animation-fill-mode: forwards;
}

Nhờ sự phân tách này, bạn có thể áp dụng từng nhóm khung hình chính riêng biệt theo ý muốn vì các thuộc tính transform hiện đã trở thành các thuộc tính riêng lẻ và không còn ghi đè lên nhau nữa. Ở trên, bạn có thể đặt thời gian riêng cho mỗi phép biến đổi mà không cần phải viết lại toàn bộ.

Hiệu suất

Ảnh động sử dụng các thuộc tính mới này cũng hiệu quả như ảnh động của thuộc tính transform hiện có.

Ảnh động của translate, rotatescale chạy trên trình tổng hợp giống như cách mà ảnh động của transform chạy, vì vậy, chúng phù hợp với hiệu suất ảnh động theo cách tương tự như transform.

Các thuộc tính mới này cũng hoạt động với thuộc tính will-change. Nói chung, tốt nhất là tránh lạm dụng will-change bằng cách sử dụng will-change với số lượng phần tử tối thiểu cần thiết và trong khoảng thời gian ngắn nhất có thể. Tuy nhiên, bạn cũng nên càng cụ thể càng tốt. Ví dụ: nếu đang sử dụng will-change để tối ưu hoá ảnh động với các thuộc tính rotatefilter, bạn nên khai báo điều này bằng cách sử dụng will-change: rotate, filter. Cách này sẽ tốt hơn một chút so với việc sử dụng will-change: transform, filter trong trường hợp bạn tạo ảnh động cho rotatefilter, vì một số cấu trúc dữ liệu mà Chrome tạo trước khi bạn sử dụng will-change có sự khác biệt giữa transformrotate.

Một phần của Loạt chương trình tương tác mới