สมมติว่ามีความต้องการฟังก์ชันแอนิเมชั่นดังกล่าว: เปลี่ยนความกว้างของ DIV จาก 100px เป็น 200px รหัสที่เขียนอาจมีลักษณะเช่นนี้:
การคัดลอกรหัสมีดังนี้:
<div id = "test1"> </div>
ฟังก์ชั่น animate1 (องค์ประกอบ, endvalue, ระยะเวลา) {
var startTime = new Date ()
startValue = parseInt (element.style.width)
ขั้นตอน = 1;
var timerid = setInterval (ฟังก์ชัน () {
var nextValue = parseInt (element.style.width) + ขั้นตอน;
element.style.width = nextValue + 'px';
if (nextValue> = endValue) {
ClearInterval (Timerid);
// ใช้เวลานานในการแสดงภาพเคลื่อนไหว
element.innerhtml = วันที่ใหม่ - เริ่มต้น;
-
}, Duration / (endValue - startValue) * ขั้นตอน);
-
animate1 (document.getElementById ('test1'), 200, 1,000);
หลักการคือการเพิ่ม 1px ทุกครั้งจนถึง 200px อย่างไรก็ตามเวลาแสดงผลหลังจากแอนิเมชั่นจบลงมากกว่า 1 วินาที (โดยปกติจะอยู่ที่ 1.5s) เหตุผลก็คือ SetInterval ไม่สามารถรับประกันช่วงเวลาการดำเนินการได้อย่างเคร่งครัด
มีวิธีที่ดีกว่านี้ไหม ก่อนอื่นดูปัญหาคณิตศาสตร์ระดับประถมศึกษา:
การคัดลอกรหัสมีดังนี้:
การสร้าง A และอาคาร B อยู่ห่างกัน 100 เมตร ชายคนหนึ่งเดินจากการสร้าง A เพื่อสร้าง B ด้วยความเร็วคงที่ หลังจากเดินเป็นเวลา 5 นาทีเขามาถึงจุดหมายปลายทางของเขา เขาอยู่ไกลแค่ไหนจากการสร้างในนาทีที่สาม?
สูตรการคำนวณสำหรับการคำนวณระยะเวลาที่กำหนดในช่วงความเร็วคงที่คือ: ระยะทาง * เวลา/เวลาปัจจุบัน ดังนั้นคำตอบควรเป็น 100 * 3 /5 = 60
แรงบันดาลใจจากคำถามนี้คือการเดินทางของช่วงเวลาที่กำหนดสามารถคำนวณได้ผ่านสูตรเฉพาะ ในทำนองเดียวกันค่าของช่วงเวลาหนึ่งในระหว่างกระบวนการเคลื่อนไหวสามารถคำนวณได้ผ่านสูตรแทนที่จะสะสม:
การคัดลอกรหัสมีดังนี้:
<div id = "test2"> </div>
ฟังก์ชั่น animate2 (องค์ประกอบ, endValue, ระยะเวลา) {
var startTime = new Date ()
startValue = parseInt (element.style.width);
var timerid = setInterval (ฟังก์ชัน () {
VAR เปอร์เซ็นต์ = (วันที่ใหม่ - เริ่มต้น) / ระยะเวลา;
var stepvalue = startValue + (endValue - startValue) * เปอร์เซ็นต์;
element.style.width = stepvalue + 'px';
ถ้า (เปอร์เซ็นต์> = 1) {
ClearInterval (Timerid);
element.innerhtml = วันที่ใหม่ - เริ่มต้น;
-
}, 13);
-
animate2 (document.getElementById ('test2'), 200, 1,000);
หลังจากการปรับปรุงนี้คุณจะเห็นว่าเวลาดำเนินการแอนิเมชั่นจะใช้เวลามากถึง 10 มิลลิวินาทีเท่านั้น อย่างไรก็ตามปัญหายังไม่ได้รับการแก้ไขอย่างสมบูรณ์ หากคุณตรวจสอบองค์ประกอบ Test2 ในเครื่องมือพัฒนาเบราว์เซอร์คุณจะพบว่าความกว้างสุดท้ายของ Test2 อาจมากกว่า 200px หากคุณตรวจสอบรหัสของฟังก์ชั่น animate2 อย่างระมัดระวังคุณจะพบ:
1. ค่าเปอร์เซ็นต์อาจมากกว่า 1 ซึ่งสามารถแก้ไขได้โดยการ จำกัด ค่าสูงสุดโดย Math.min
2. แม้ว่ามูลค่าของเปอร์เซ็นต์จะรับประกันว่าจะไม่เกิน 1 ตราบใดที่ endvalue หรือ startValue เป็นทศนิยมค่าของ (endvalue - startValue) * เปอร์เซ็นต์อาจทำให้เกิดข้อผิดพลาดเนื่องจากความแม่นยำของการทำงานของทศนิยม JavaScript ไม่เพียงพอ ในความเป็นจริงสิ่งที่เราต้องการเพื่อให้แน่ใจคือความถูกต้องของค่าสุดท้ายดังนั้นเมื่อเปอร์เซ็นต์คือ 1 เพียงแค่ใช้ endvalue โดยตรง
ดังนั้นรหัสของฟังก์ชั่น animate2 จึงถูกแก้ไขเป็น:
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น animate2 (องค์ประกอบ, endValue, ระยะเวลา) {
var startTime = new Date ()
startValue = parseInt (element.style.width);
var timerid = setInterval (ฟังก์ชัน () {
// ตรวจสอบให้แน่ใจว่าเปอร์เซ็นต์ไม่เกิน 1
var เปอร์เซ็นต์ = math.min (1, (วันที่ใหม่ - เวลาเริ่มต้น) / ระยะเวลา);
var stepvalue;
ถ้า (เปอร์เซ็นต์> = 1) {
// ตรวจสอบความถูกต้องของค่าสุดท้าย
stepvalue = endvalue;
} อื่น {
stepValue = startValue + (endValue - startValue) * เปอร์เซ็นต์;
-
element.style.width = stepvalue + 'px';
ถ้า (เปอร์เซ็นต์> = 1) {
ClearInterval (Timerid);
element.innerhtml = วันที่ใหม่ - เริ่มต้น;
-
}, 13);
-
มีอีกคำถามสุดท้าย: ทำไมช่วงเวลาของ setInterval จึงตั้งค่าเป็น 13ms? เหตุผลก็คืออัตราการรีเฟรชของจอภาพในปัจจุบันโดยทั่วไปไม่เกิน 75Hz (นั่นคือมันรีเฟรช 75 ครั้งต่อวินาทีซึ่งหมายความว่ามันจะรีเฟรชทุก 13ms) และการซิงโครไนซ์ช่วงเวลากับอัตราการรีเฟรชดีกว่า