ตัวจับเวลาเป็นเทคโนโลยีหลักของแอนิเมชั่น JavaScript มาโดยตลอด กุญแจสำคัญในการเขียนลูปแอนิเมชั่นคือการรู้ว่าเวลาหน่วงนั้นนานแค่ไหน ในแง่หนึ่ง ช่วงเวลาการวนซ้ำต้องสั้นพอที่จะทำให้เอฟเฟ็กต์ภาพเคลื่อนไหวต่างๆ ดูราบรื่น ในทางกลับกัน ช่วงเวลาการวนซ้ำต้องยาวเพียงพอเพื่อให้แน่ใจว่าเบราว์เซอร์สามารถแสดงการเปลี่ยนแปลงที่เกิดขึ้นได้
อัตราการรีเฟรชของจอคอมพิวเตอร์ส่วนใหญ่คือ 60Hz ซึ่งเท่ากับประมาณ 60 การวาดใหม่ต่อวินาที เบราว์เซอร์ส่วนใหญ่จะจำกัดการดำเนินการวาดใหม่ให้ไม่เกินความถี่การวาดใหม่ของจอแสดงผล เนื่องจากแม้จะเกินความถี่นั้น ประสบการณ์ผู้ใช้ก็จะไม่ได้รับการปรับปรุง ดังนั้น ช่วงเวลาการวนซ้ำที่เหมาะสมที่สุดสำหรับภาพเคลื่อนไหวที่ราบรื่นที่สุดคือ 1000ms/60 ซึ่งเท่ากับประมาณ 16.6ms
ปัญหาของ setTimeout และ setInterval คือมันไม่แม่นยำ กลไกการทำงานภายในกำหนดว่าพารามิเตอร์ช่วงเวลาจริงๆ เพียงระบุเวลาในการเพิ่มโค้ดภาพเคลื่อนไหวลงในคิวเธรด UI ของเบราว์เซอร์เพื่อรอการดำเนินการ หากมีการเพิ่มงานอื่นไว้ที่ด้านหน้าของคิว โค้ดภาพเคลื่อนไหวต้องรอจนกว่างานก่อนหน้าจะเสร็จสิ้นก่อนจึงจะดำเนินการได้
requestAnimationFrame ใช้ช่วงเวลาของระบบเพื่อรักษาประสิทธิภาพการวาดภาพให้ดีที่สุด โดยจะไม่ทำให้การวาดภาพเกินและเพิ่มโอเวอร์เฮดเนื่องจากช่วงเวลาสั้นเกินไป นอกจากนี้ยังจะไม่ทำให้ภาพเคลื่อนไหวติดขัดและไม่ราบรื่นเนื่องจากช่วงเวลายาวเกินไป เอฟเฟกต์ภาพเคลื่อนไหวของหน้าเว็บต่างๆ สามารถทำได้ มีกลไกการรีเฟรชแบบครบวงจรเพื่อประหยัดทรัพยากรระบบ ปรับปรุงประสิทธิภาพของระบบ และปรับปรุงเอฟเฟ็กต์ภาพ
คุณสมบัติเมธอด requestAnimationFrame รับการเรียกกลับเป็นพารามิเตอร์ และฟังก์ชันการเรียกกลับจะถูกส่งผ่านในพารามิเตอร์ DOMHighResTimeStamp ซึ่งระบุเวลาที่ฟังก์ชันการเรียกกลับที่เรียงลำดับตาม requestAnimationFrame() ถูกทริกเกอร์ในปัจจุบัน ค่าที่ส่งคืนคือรหัสคำขอซึ่งแสดงถึงตัวระบุที่ไม่ซ้ำกันในรายการโทรกลับ ค่านี้สามารถส่งผ่านไปยัง window.cancelAnimationFrame() เพื่อยกเลิกฟังก์ชันการโทรกลับ
requestID = window.requestAnimationFrame (โทรกลับ);
เมื่อใช้ API นี้ โค้ดบางรายการสามารถดำเนินการได้ในระหว่างการเรนเดอร์ครั้งถัดไป เพื่อหลีกเลี่ยงไม่ให้เกิดการจัดเรียงซ้ำจำนวนมากในช่วงเวลาสั้นๆ
ตัวอย่างเช่น ฟังก์ชันเรียกกลับของเหตุการณ์การเลื่อนหน้า (การเลื่อน) เหมาะมากสำหรับการใช้ API นี้ โดยเลื่อนการดำเนินการเรียกกลับออกไปจนกว่าจะแสดงผลอีกครั้งครั้งถัดไป อย่างไรก็ตาม ควรสังเกตว่า requestAnimationFrame ไม่ได้จัดการฟังก์ชันการโทรกลับ กล่าวคือ การเรียก requestAnimationFrame ด้วยฟังก์ชันการโทรกลับเดียวกันหลายครั้งก่อนที่จะดำเนินการโทรกลับจะทำให้การโทรกลับถูกดำเนินการหลายครั้งในเฟรมเดียวกัน วิธีที่ง่ายที่สุดคือการใช้ฟังก์ชันควบคุมปริมาณเพื่อแก้ไขปัญหานี้ หรือคุณสามารถหาวิธีที่จะมีฟังก์ชันเรียกกลับเดียวกันเพียงฟังก์ชันเดียวในคิวของ requestAnimationFrame:
ให้ scheduleAnimationFrame = false;document.body.onscroll = () => { if (scheduledAnimationFrame) return; scheduleAnimationFrame = true; window.requestAnimationFrame(() => { scheduleAnimationFrame = false; // do some });};
แน่นอนว่าสถานการณ์การใช้งานแอปพลิเคชันที่ดีที่สุดยังคงอยู่ในเฟรมแอนิเมชั่น ซึ่งสามารถเพิ่มประสิทธิภาพได้อย่างมาก
คำถามสัมภาษณ์ วิธีเรนเดอร์ข้อมูลนับหมื่นโดยไม่ติดค้างอยู่ในอินเทอร์เฟซคำถามนี้จะตรวจสอบวิธีการเรนเดอร์ข้อมูลโดยไม่ปิดกั้นเพจ กล่าวคือ คุณไม่สามารถเรนเดอร์รายการหลายหมื่นรายการพร้อมกันได้ แต่ควรเรนเดอร์ส่วนหนึ่งของ DOM ในคราวเดียว จากนั้นคุณสามารถรีเฟรชได้ทุกๆ 16 มิลลิวินาทีผ่าน requestAnimationFrame
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, Initial-scale=1.0> <meta http-equiv=X-UA - เนื้อหาที่เข้ากันได้=ie=edge> <title>เอกสาร</title></head><body> <ul>การควบคุม</ul> <script> setTimeout(() => { // ใส่ข้อมูล 100,000 ชิ้น const รวม = 100,000 // ใส่ครั้งละ 20 ชิ้น ถ้ารู้สึกว่าประสิทธิภาพไม่ดี ให้ลด const หนึ่งครั้ง = 20 // ต้องใช้กี่ครั้งจึงจะ render ข้อมูลได้? เมื่อให้ countOfRender = 0 ให้ ul = document.querySelector(ul); function add() { // ปรับประสิทธิภาพให้เหมาะสม การแทรกจะไม่ทำให้เกิด backflow constแฟรกเมนต์ = document.createDocumentFragment(); for (let i = 0; i < i++) { const li = document.createElement(li); li.innerText = Math.floor(Math.random() * รวม); 1; loop(); } ฟังก์ชัน loop() { if (countOfRender < loopCount) { window.requestAnimationFrame(เพิ่ม); วนซ้ำ(); }, 0); </script></body></html>ความเข้ากันได้
เบราว์เซอร์เก่าบางรุ่นไม่รองรับ API นี้ หากต้องการใช้ API นี้ คุณสามารถปรับแต่งวิธีการนี้และติดตั้งไว้ใต้หน้าต่างได้:
(function() { var LastTime = 0; var vendors = ['webkit', 'moz']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[ผู้ขาย[x]+'CancelAnimationFrame'] ||. window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(โทรกลับ) { var currTime = new Date().getTime(); 0, 16 - (currTime - LastTime)); var id = window.setTimeout(function() { โทรกลับ (currTime + timeToCall); }, timeToCall); LastTime = currTime + timeToCall; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = ฟังก์ชั่น(id) { clearTimeout(id)
ข้างต้นคือเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาของทุกคน ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network