หากใช้ requestAnimationFrame
คุณสนุกกับการเห็นสีที่ซิงค์กับอัตราการรีเฟรชของหน้าจอ ทำให้ได้ภาพเคลื่อนไหวที่มีความแม่นยำสูงมากที่สุด อีกทั้งคุณยังสามารถประหยัดเสียงรบกวนจากพัดลมของ CPU และพลังงานแบตเตอรี่เมื่อผู้ใช้เปลี่ยนไปใช้แท็บอื่น
แต่กำลังจะมีการเปลี่ยนแปลงบางอย่างใน API การประทับเวลาที่ส่งไปยังฟังก์ชันเรียกกลับจะเปลี่ยนจากการประทับเวลาทั่วไปที่คล้ายกับ Date.now()
เป็นการวัดความละเอียดสูงของจุดลอยตัวในหน่วยมิลลิวินาทีนับจากที่เปิดหน้า หากใช้ค่านี้ คุณจะต้องอัปเดตโค้ดโดยอิงตามคำอธิบายด้านล่าง
เพื่อความชัดเจน เกี่ยวกับสิ่งที่เรากำลังพูดถึง:
// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
// the value of timestamp is changing
});
หากคุณใช้การแสดงผล requestAnimFrame
ทั่วไปที่ให้ไว้ที่นี่ แสดงว่าคุณไม่ได้ใช้ค่าการประทับเวลา คุณมาถูกทางแล้ว :)
ทำไมจึงควร
เหตุผล อัตรา rAF จะช่วยให้คุณได้ 60 fps ที่ดีที่สุด และ 60 fps แปลเป็น 16.7 มิลลิวินาทีต่อเฟรม แต่การวัดด้วยจำนวนเต็มมิลลิวินาทีหมายความว่าเรามีความแม่นยำเป็น 1/16 สำหรับทุกสิ่งที่เราต้องการสังเกตการณ์และกำหนดเป้าหมาย
จากที่เห็นด้านบน แถบสีน้ำเงินคือระยะเวลาสูงสุดที่คุณต้องทำงานทั้งหมดก่อนที่จะวาดเฟรมใหม่ (ที่ 60 FPS) คุณอาจกำลังทำสิ่งต่างๆ มากกว่า 16 อย่าง แต่เมื่อใช้จำนวนเต็มมิลลิวินาที คุณจะสามารถกำหนดเวลาและวัดผลในส่วนที่แบ่งเป็นส่วนๆ เท่านั้นได้ ยังไม่ดีพอ
ซึ่งตัวจับเวลาความละเอียดสูงจะแก้ปัญหานี้โดยแสดงข้อมูลตัวเลขที่แม่นยำมากขึ้น
Date.now() // 1337376068250
performance.now() // 20303.427000007
ปัจจุบันตัวจับเวลาความละเอียดสูงพร้อมใช้งานใน Chrome ในชื่อ window.performance.webkitNow()
และโดยทั่วไปค่านี้จะเท่ากับค่าอาร์กิวเมนต์ใหม่ที่ส่งผ่านไปยังโค้ดเรียกกลับ rAF เมื่อข้อกำหนดผ่านมาตรฐานมากขึ้นแล้ว เมธอดจะเลิกใช้คำนำหน้าและอนุญาตให้ใช้ได้ถึง performance.now()
นอกจากนี้ คุณยังสังเกตเห็นว่าค่าสองค่าข้างต้นมีลำดับขนาดแตกต่างกัน performance.now()
คือการวัดจำนวนจุดลอยตัวเป็นมิลลิวินาทีนับจากที่หน้านั้นเริ่มโหลด (performance.navigationStart
จะระบุอย่างเจาะจง)
ใช้งานอยู่
ปัญหาหลักที่การครอบตัดคือไลบรารีภาพเคลื่อนไหวที่ใช้รูปแบบการออกแบบต่อไปนี้
function MyAnimation(duration) {
this.startTime = Date.now();
this.duration = duration;
requestAnimFrame(this.tick.bind(this));
}
MyAnimation.prototype.tick = function(time) {
var now = Date.now();
if (time > now) {
this.dispatchEvent("ended");
return;
}
...
requestAnimFrame(this.tick.bind(this));
}
การแก้ไขเพื่อแก้ไขปัญหานี้ค่อนข้างง่าย... เพิ่ม startTime
และ now
เพื่อใช้ window.performance.now()
this.startTime = window.performance.now ?
(performance.now() + performance.timing.navigationStart) :
Date.now();
วิธีนี้เป็นการใช้งานที่ค่อนข้างซื่อตรง ไม่ได้ใช้เมธอด now()
นำหน้าและยังถือว่ามีการรองรับ Date.now()
ซึ่งไม่มีใน IE8
การตรวจหาฟีเจอร์
หากคุณไม่ได้ใช้รูปแบบข้างต้นและต้องการระบุเฉพาะค่าโค้ดเรียกกลับที่คุณได้รับ คุณสามารถใช้เทคนิคนี้
requestAnimationFrame(function(timestamp){
if (timestamp < 1e12){
// .. high resolution timer
} else {
// integer milliseconds since unix epoch
}
// ...
การตรวจสอบ if (timestamp < 1e12)
เป็นการทดสอบสั้นๆ เพื่อดูว่าเรากำลังรับมือกับตัวเลขจำนวนมากแค่ไหน ในทางเทคนิค อาจเกิดข้อผิดพลาดขึ้นเมื่อหน้าเว็บเปิดต่อเนื่องเป็นเวลา 30 ปีเท่านั้น แต่เราไม่สามารถทดสอบได้ว่าตัวเลขดังกล่าวเป็นเลขทศนิยมหรือไม่ (แทนที่จะกำหนดเป็นจำนวนเต็ม) ขอให้ส่งตัวจับเวลาที่มีความละเอียดสูงเพียงพอ จากนั้นคุณจะได้ค่าจำนวนเต็มในบางเวลา
เราวางแผนที่จะนำการเปลี่ยนแปลงนี้ใน Chrome 21 ไปใช้ ดังนั้นหากคุณใช้ประโยชน์จากพารามิเตอร์โค้ดเรียกกลับนี้อยู่แล้ว โปรดอัปเดตโค้ดของคุณ