+1

CSS Hiệu ứng ảnh 3D

Kết quả chúng ta sẽ thu được:

Thực hiện thôi nào, Khung html cơ bản:

<!DOCTYPE html>
<html>
  <head>
    <title>
      Hiệu ứng 3D
    </title>
    <link rel='stylesheet' type='text/css' href='style.css'/>
  </head>
  <body>
    <div class='container'/>
  </body>
</html>

File style, phần cơ bản ban đầu cần có:

body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.container {
  position: relative;
  width: 360px;
  height: 640px;
  background: rgba(0,0,0,1);
}

Chúng ta được:

Hơi to và không đc đẹp cho lắm, xoay nó và scale nó nhỏ lại thôi.

.container {
  position: relative;
  width: 360px;
  height: 640px;
  background: rgba(0,0,0,1);
  transform: rotate(-30deg) skew(25deg) scale(.8);
  transition: 0.5s;
}

Kết quả:

Thêm cái ảnh vào cho nó sinh động:

    <div class='container'>
      <img src='demo.jpg'/>
      <img src='demo.jpg'/>
      <img src='demo.jpg'/>
      <img src='demo.jpg'/>
    </div>

Phải viết 1 chút style cho nó fill vào thằng cha nữa:

.container img {
  position: absolute;
  width: 100%;
  transition: 0.5s;
}

Chúng ta được:

Thêm hiệu ứng hover cho "nó":

.container:hover img:nth-child(1){
  transform: translate(160px, -160px);
}

Có vẻ thứ tự đang không được đúng lắm, chúng đang đè lên nhau, chỉnh sửa 1 chút lại thứ tự vị trí các layer và độ nét:


.container:hover img:nth-child(4){
  transform: translate(160px, -160px);
  opacity: 1;
}

.container:hover img:nth-child(3){
  transform: translate(120px, -120px);
  opacity: .8;
}

.container:hover img:nth-child(2){
  transform: translate(80px, -80px);
  opacity: .6;
}

.container:hover img:nth-child(1){
  transform: translate(40px, -40px);
  opacity: .4;
}

Ta được:

Nền hơi xấu, chỉnh sửa 1 chút màu nên cho đẹp:

.container {
  background: rgba(0,0,0,.1);
}

Kết quả mĩ mãn:

Nguồn học tập: Youtube
Giải thích một số thuộc tính:
transittion: 0.5s; là thuộc tính để tạo animation thiệt là smooth, nếu không có thuộc tính này thì effect của chúng ta sẽ nhìn như thế này:

transform: rotate(-30deg) skew(25deg) scale(.8);

  • rotate(-30deg) quay hình ngược lại với kim đồng hồ 30 độ.
  • skew(25deg) quay theo trục 2D, nó sẽ giúp | -> \ kiểu vậy =)).
  • scale thì là thu phóng rồi. Tác dụng của skew:

Trong hầu hết các trường hợp thì dùng rotate, skew, scale đều ổn, và nó là cách dễ nhất để thực hiện. Nhưng thử làm với một cách khó hơn xem sao. matrix
Thay vì phải dùng đến 3 thuộc tính thì ta dùng một thuộc tính matrix thay thế cho cả 3 thuộc tính trên, và ta có:

transform: rotate(-30deg) skew(25deg) scale(.8);

->

transform: matrix(0.69282, 0.4, 0.723067, 0.506297, 0, 0);

Nhìn múa lửa hơn nhiều.

Bài viết này hơi ngắn nên có lẽ mình sẽ viết 1 chút về matrix. Mình cũng chưa xem phim matrix bao giờ nhưng mà trong toán học thì ma trận là:

Mình cũng không phải đứa hay được trên 5 điểm toán nên xin phép không bàn sâu về các vấn đề như a như b mà chỉ là đọc bài báo trên mạng và dẫn về thôi ạ.

chúng ta có matrixmatrix3D tương được với việc ma trận 3x3 và ma trận 4x4 được dùng để tính toán cho 'sự' biến đổi của chúng.

Mình chỉ xin nghiên cứu về ma trận 3x3:

tương đương với matrix(a,b,c,d,e,f)

Khi sử dụng matrix, trình duyệt sẽ nhân ma trận mà chúng ta truyền vào với một vector [x, y, 1], trong đó thì x và y là tọa độ của 1 điểm cụ thể trong 'local coordinate space'

Cách mà phép toán thực hiện:

Vẫn rất khó hiểu nhỉ =))

Ví dụ cụ thể nhé các bạn:

#mydiv{
	transform: matrix(1, 0, 0, 1, 150, 150);
	}

tương đương với transform: translate(150px, 150px);

Đây là cách mà trình duyệt tính toán:

=> Trong #mydiv pixel tại position 220px, 220px sẽ hiển thị tại vị trí 370px, 370px khi được apply thuộc tinh css này.

Quay lại nội dung chính của bài viết:

đoạn thuộc tính:

transform: rotate(-30deg) skew(25deg) scale(.8);

Cùng thử tính xem liệu nó có ra đúng như tôi đã nói ở trên:

transform: matrix(0.69282, -0.4, 0.723067, 0.506297, 0, 0);

Sử dụng event onmousemove để lấy ra clientX và clientY từ đó xác định đc vị trí của point (780, 150) sau khi transform là (650, 390).

function showCoords(event) {
    var x = event.clientX;
    var y = event.clientY;
    var coor = "X coords: " + x + ", Y coords: " + y;
    console.log(coor);
}

Sau đó gán function vào event onmousemove của body, đọc log trong console chúng ta sẽ biết được tọa độ điểm trước và sau khi transform.

Cùng thử tính xem nhé

ta có matrix(0.69282, 0.4, 0.723067, 0.506297, 0, 0) nhân với vector(150, 780, 1)

0.69282 0.723067 0     780   540,3996 108,46005 0   648.85965
0.4     0.506297 0  x  150 = 312      75,94455  0 = 387.94455
0       0        1     1     0        0         1   1

-> điểm là (649, 388) khá là khớp, chắc sai số do tính toán với thập phân =))

Cái đoạn param của matrix trên là mình xài tool generate ra đó các bạn ạ hehe.

Phần matrix3d thì cũng tương tự với matrix thôi, chỉ là nó là ma trận 4x4 nên sẽ có thể truyền nhiều param vào hơn và xoay theo góc sâu đc. Nghe vậy thôi đã thấy hại não rồi 😦.

#mydiv{
	transform: matrix3d(.8, 0, 0, 0, 0, .5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
	}

Phần này thì bạn nào có nhu cầu tìm hiểu sâu nữa thì vào link bên dưới nhé 😄

Cảm ơn các bạn đã theo dõi.

Nguồn đoạn này:

https://dev.opera.com/articles/understanding-the-css-transforms-matrix/


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí