Ta lại quay lại về cái đếm ngược Oh Noes.
Giờ nếu ta muốn ảnh của Oh Noes to dần ra
khi đếm ngược dần về 0,
thì phải làm thế nào?
Một cách làm là tạo ảnh động
với CSS của ảnh này với window.setInterval.
Bước đầu tiên, tôi sẽ tìm ảnh này
và gán nó vào một biến.
ohnoes = document.getElemenyById("ohnoes");
Ta đặt style khởi điểm,
tức là sẽ bắt đầu từ chiều rộng này.
Rồi ảnh sẽ lớn dần ra từ đó.
Giờ ta viết một hàm makeItBigger
để làm ảnh to ra từng chút một.
Ở đây ta lấy giá trị style.width,
lấy giá trị style.width từ trước và cộng thêm 1 vào.
Cuối cùng tôi sẽ gọi hàm setInterval với hàm này.
window.setInterval(makeItBigger),
Ta muốn nó to lên từng nào nào?
Hỏi cách khác là cứ bao lâu thì sẽ to lên 1 lần?
Nếu ta ma muốn tạo một hình ảnh động thật mượt,
thì tức là sẽ cần thay đổi trong khoảng tần suất
24 khung hình mỗi giây tới 60 khung hình mỗi giây.
Tôi sẽ thử với 30 khung hình mỗi giây, tức là 1000/3.
Không được rồi.
Bạn biết tại sao không? Hơi rắc rối đấy.
Ta sẽ xem lại xem nào.
Giá trị của ohnoes.style.width
sau khi chạy dòng lệnh này là bao nhiêu nào?
Chắc là 50px rồi sẽ đến 51px rồi,
nhưng ta cứ log ra xem ohnoes.style.width là bao nhiêu.
Ta đặt cái này vào trong infoDiv.
Nó sẽ bằng...
50px, okay.
Rồi khi ta cộng thêm 1 vào 50px,
50px thêm 1 là gì?
Bạn đoán là 51px, nhưng JS
coi 50px là 1 string,
nên thêm 1 sẽ thành 50px1,
tức là chả có ý nghĩa gì.
Như vậy là trình duyệt sẽ không
thay đổi thuộc tính width theo giá trị dở hơi này được rồi.
Vậy là ta sẽ cần chuyển đổi string với đơn vị pixel này
về kiểu số,
rồi cộng 1 vào số đó,
rồi lại thêm "px" vào sau.
Ta có thể đặt cái này vào trong parseFloat,
thế là đổi được về dạng số.
Rồi ta đóng ngoặc cụm này lại,
và thêm "px" vào sau.
Được rồi. Ảnh đang to dần lên rồi.
Bạn thấy cái lằng nhằng
trong việc tạo hình động với CSS
là thường nó sẽ có cả chữ đơn vị ở sau giá trị số nữa, bạn sẽ phải
chuyển bỏ đơn vị đó đi... trời ơi ảnh to quá...
bạn phải bỏ chữ đơn vị đó ra rồi lại đưa nó lại vào sau.
Ảnh này to ra quá rồi.
Còn một vài vấn đề thường gặp
khi sử dụng setInterval để thay đổi thuộc tính CSS.
Đầu tiên là trình duyệt sẽ không phải lúc nào cũng
đợi đúng theo số interval này.
Nếu có event gì khác xảy ra, như là khi người dùng sử dụng trình duyệt,
gõ gì đó chẳng hạn, thì có thể trình duyệt sẽ đợi xong event đó mới gọi hàm callback này,
thì hoạt hình động trông sẽ không được mượt.
Thứ 2 nữa là trình duyệt sẽ gọi hàm này
kể cả khi tab này ẩn đi,
tức là sẽ tiêu tốn tài nguyên của máy tính.
Vì vậy nên là các trình duyệt hiện đại
có một hàm mới,
chuyên dùng để tạo hoạt hình với DOM,
gọi là window.requestAnimationFrame.
Làm việc với hàm đó, đầu tiên ta sẽ bỏ dòng setInterval này đi
và gọi hàm requestAnimationFrame()
ở trong hàm này.
Và ta sẽ chỉ nó đến
hàm makeItBigger.
Rồi sẽ sẽ gọi hàm makeItBigger() ngay khi tải trang web.
Oh! Ảnh này đang to lên nahnh quá.
Trình duyệt đang gọi hàm makeItBigger liên tục
mỗi khi cập nhật ảnh, tức là vào khoảng 60 khung hình một giây,
tức là gấp đôi tần số vừa rồi.
Hàm này cứ mỗi lần lại cộng thêm 1px vào chiều rộng,
tính toán ra thì
là cộng thêm 60px mỗi giây.
Chỉ vài giây là ảnh đã to hơn cả trang rồi.
Giờ to quá đi mất rồi.
Vậy làm sao để làm chậm hoạt hình này lại?
Có một vài cách, nhưng một cách tôi thích dùng
là kiểm tra xem đã chạy bao nhiêu giây rồi,
rồi tính giá trị của chiều rộng
dựa theo giá trị đó.
Ta bắt đầu chép lại thời gian khởi điểm, tính theo ms,
trước khi hàm này được gọi.
var startTime... ảnh lại to ra nữa rồi.
new Date().getTime();
Trong makeItBigger9) thì ta lưu giá trị của thời gian hiện tại.
var currTime = new Date().getTime();
Giờ ta phải tính,
ví dụ nếu muốn ảnh to ra 30px/s,
và bắt đầu từ 50px,
ta tính toán ở đây.
newWidth bằng 50 + ..., 50 là giá trị khởi điểm...
cộng thêm currentTime trừ đi startTime.
Giá trị này là millisecond, nên ta sẽ
chia cho 1000,
rồi nhân với 30,
bỏi vì ta muốn tăng lên 30px mỗi giây.
Đây là newWidth rồi.
Giờ ta sẽ đặt style.width cho bằng newWidth.
newWidth... đây được rồi,
thế này là được 30px/s thật mượt rồi.
Ta có thể thay đổi số này nếu muốn nó chạy
nhanh hơn chậm hơn.
Còn nếu muốn dừng hoạt hình lại khi to đủ rồi thì sao?
Ta có thể cho dòng này vào trong điều kiện 'if'.
Dòng này đây, và chỉ chạy dòng này
nếu currentWidth nhỏ hơn 1 giá trị nào đó, if the currentWidth is
như là 300, thử xem nào.
Thực ra không phải là currentWidth mà là newWidth mới được.
Thử xem có dừng ở 300 không.
Oh Noes ơi, to ra xem nào.
Đẹp rồi.
Kĩ thuật sử dụng requestAnimationFrame này
hoàn toàn dùng được với Chrome,
Firefox và IE10 trở lên.
Còn có những thư viện JS
để dùng requestAnimationFrame nếu được,
và quay lai jdungf setInterval nếu là trình duyệt cũ.
Đấy là một vấn đề của việc lập trình web:
Mạng web thay đổi liên tục,
các trình duyệt liên tục cung cấp các chức năng mới,
lập trình viên cũng phát triển các kĩ thuật mới.
Bạn cần liên tục học về những cái mới này
thì sử dụng mới hiệu quả tối đa được.