แอปพลิเคชันวาดภาพที่ใช้ปากกาสไตลัสซึ่งสร้างขึ้นสำหรับเว็บประสบปัญหาเกี่ยวกับเวลาในการตอบสนองมาอย่างยาวนาน เนื่องจากหน้าเว็บต้องซิงค์การอัปเดตกราฟิกกับ DOM ในแอปพลิเคชันวาดภาพใดๆ เวลาในการตอบสนองนานกว่า 50 มิลลิวินาทีอาจรบกวนการทำงานของมือและตาของผู้ใช้ ทำให้แอปพลิเคชันใช้งานยาก
คำแนะนำ desynchronized
สำหรับ canvas.getContext()
จะเรียกใช้เส้นทางโค้ดอื่นที่ข้ามกลไกการอัปเดต DOM ตามปกติ
แต่จะบอกให้ระบบพื้นฐานข้ามการคอมโพสได้มากเท่าที่จะทำได้ และในบางกรณี ระบบจะส่งบัฟเฟอร์พื้นฐานของ Canvas ไปยังตัวควบคุมการแสดงผลของหน้าจอโดยตรง วิธีนี้จะช่วยขจัดเวลาในการตอบสนองที่อาจเกิดขึ้นจากการใช้คิวคอมโพสิตโปรแกรมแสดงผล
ผลิตภัณฑ์ดีแค่ไหน
หากต้องการดูรหัส ให้เลื่อนไปข้างหน้า หากต้องการดูวิธีการใช้งาน คุณต้องมีอุปกรณ์ที่มีหน้าจอสัมผัส และควรมีปากกาสไตลัส (ใช้นิ้วได้เช่นกัน) หากมี ให้ลองใช้ตัวอย่าง 2d หรือ webgl ส่วนผู้ใช้งานคนอื่นๆ โปรดดูการสาธิตโดย Miguel Casas ซึ่งเป็นวิศวกรที่ติดตั้งใช้งานฟีเจอร์นี้ เปิดเดโม กดเล่น แล้วเลื่อนแถบเลื่อนไปมาแบบสุ่มและรวดเร็ว
ตัวอย่างนี้ใช้คลิปความยาว 1 นาที 21 วินาทีจากภาพยนตร์สั้น Sintel โดย Durian ซึ่งเป็นโปรเจ็กต์ภาพยนตร์โอเพนซอร์สของ Blender ในตัวอย่างนี้ ภาพยนตร์จะเล่นในองค์ประกอบ <video>
ซึ่งเนื้อหาจะแสดงผลในองค์ประกอบ <canvas>
พร้อมกัน อุปกรณ์จํานวนมากทําเช่นนี้ได้โดยไม่ฉีกขาด แต่อุปกรณ์ที่มีการเรนเดอร์บัฟเฟอร์ด้านหน้า เช่น ChromeOS อาจฉีกขาด (ภาพยนตร์เรื่องนี้ยอดเยี่ยมแต่ก็น่าเศร้า
ฉันทำอะไรไม่ได้เลยเป็นเวลา 1 ชั่วโมงหลังจากเห็น โปรดรับทราบคำเตือนนี้)
การใช้คำแนะนำ
การใช้เวลาในการตอบสนองต่ำนั้นมีประโยชน์มากกว่าการเพิ่ม desynchronized
ลงใน canvas.getContext()
เราจะอธิบายปัญหาทีละรายการ
สร้างแคนวาส
ใน API อื่น เราจะต้องพูดถึงการตรวจหาฟีเจอร์ก่อน สำหรับdesynchronized
คำแนะนำ คุณต้องสร้างผืนผ้าใบก่อน เรียกใช้ canvas.getContext()
และส่งผ่านคำแนะนำ desynchronized
ใหม่ที่มีค่าเป็น true
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('2d', {
desynchronized: true,
// Other options. See below.
});
การตรวจหาองค์ประกอบ
ถัดไป ให้โทรหา getContextAttributes()
หากออบเจ็กต์แอตทริบิวต์ที่แสดงผลมีพร็อพเพอร์ตี้ desynchronized
ให้ทดสอบ
if (ctx.getContextAttributes().desynchronized) {
console.log('Low latency canvas supported. Yay!');
} else {
console.log('Low latency canvas not supported. Boo!');
}
หลีกเลี่ยงการกะพริบ
มี 2 กรณีที่อาจทำให้เกิดภาพกะพริบหากคุณเขียนโค้ดไม่ถูกต้อง
บางเบราว์เซอร์รวมถึง Chrome จะล้างแคนวาส WebGL ระหว่างเฟรม ตัวควบคุมจอแสดงผลอาจอ่านบัฟเฟอร์ขณะที่ว่างเปล่า ซึ่งทำให้รูปภาพที่วาดกระพริบ วิธีหลีกเลี่ยงปัญหานี้คือการตั้งค่า preserveDrawingBuffer
เป็น true
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('webgl', {
desynchronized: true,
preserveDrawingBuffer: true
});
นอกจากนี้ การสั่นไหวยังอาจเกิดขึ้นเมื่อคุณล้างบริบทหน้าจอในโค้ดการวาดของคุณเอง หากต้องล้าง ให้วาดลงในเฟรมบัฟเฟอร์นอกหน้าจอ แล้วคัดลอกไปยังหน้าจอ
ช่องอัลฟ่า
องค์ประกอบ Canvas แบบโปร่งแสงซึ่งตั้งค่าอัลฟ่าเป็น "จริง" จะยังคงยกเลิกการซิงค์ได้ แต่ต้องไม่มีองค์ประกอบ DOM อื่นๆ อยู่ด้านบน
มีได้เพียงรายการเดียว
คุณจะเปลี่ยนแอตทริบิวต์บริบทหลังจากการเรียกใช้ canvas.getContext()
ครั้งแรกไม่ได้ นี่เป็นความจริงมาโดยตลอด แต่การย้ำเรื่องนี้ซ้ำๆ อาจช่วยคุณประหยัดความหงุดหงิดได้หากคุณไม่ทราบหรือลืมไปแล้ว
ตัวอย่างเช่น สมมติว่าฉันได้รับบริบทและระบุ alpha เป็น false จากนั้นเรียกใช้ canvas.getContext()
ครั้งที่สองในโค้ดโดยตั้งค่า alpha เป็น true ตามที่แสดงด้านล่าง
const canvas = document.querySelector('myCanvas');
const ctx1 = canvas.getContext('2d', {
alpha: false,
desynchronized: true,
});
//Some time later, in another corner of code.
const ctx2 = canvas.getContext('2d', {
alpha: true,
desynchronized: true,
});
ctx1
และ ctx2
ไม่ใช่วัตถุเดียวกัน Alpha จะยังคงเป็นเท็จและจะไม่มีการสร้างบริบทที่มี alpha เท่ากับจริง
ประเภทแคนวาสที่รองรับ
พารามิเตอร์แรกที่ส่งไปยัง getContext()
คือ contextType
หากคุ้นเคยกับ getContext()
อยู่แล้ว คุณอาจสงสัยว่าระบบรองรับบริบทประเภทอื่นนอกเหนือจาก "2 มิติ" หรือไม่ ตารางด้านล่างแสดงประเภทบริบทที่รองรับ desynchronized
contextType | ออบเจ็กต์ประเภทบริบท |
---|---|
|
|
|
|
|
|
บทสรุป
หากต้องการดูตัวอย่างเพิ่มเติม ให้ดูที่แท็บ "ลองฟัง" นอกจากตัวอย่างวิดีโอที่อธิบายไปแล้ว ยังมีตัวอย่างที่แสดงทั้งบริบท '2d' และ 'webgl'