แอปพลิเคชันการวาดภาพที่ใช้สไตลัสสร้างขึ้นสำหรับเว็บได้รับปัญหาด้านเวลาในการตอบสนองเป็นเวลานานเนื่องจากหน้าเว็บต้องซิงค์ข้อมูลการอัปเดตกราฟิกกับ DOM ในแอปพลิเคชันการวาดภาพ เวลาในการตอบสนองที่นานกว่า 50 มิลลิวินาทีอาจรบกวนการทำงานที่ประสานกันระหว่างมือและตาของผู้ใช้ ซึ่งทำให้แอปพลิเคชันใช้งานได้ยาก
คำแนะนำ desynchronized
สำหรับ canvas.getContext()
จะเรียกใช้เส้นทางโค้ดอื่นที่ข้ามกลไกการอัปเดต DOM ปกติ
แต่คำแนะนำจะบอกให้ระบบที่สำคัญข้ามการประสานให้มากที่สุดเท่าที่จะทำได้ และในบางกรณี บัฟเฟอร์ที่สำคัญของ Canvas จะถูกส่งไปยังตัวควบคุมการแสดงผลของหน้าจอโดยตรง ซึ่งจะลดเวลาในการตอบสนองที่อาจเกิดขึ้นจากการใช้คิวคอมโพสิเตอร์ของโหมดแสดงภาพ
ผลิตภัณฑ์ดีแค่ไหน
หากต้องการดูรหัส ให้เลื่อนไปข้างหน้า หากต้องการดูการใช้งานจริง คุณต้องมีอุปกรณ์ที่มีหน้าจอสัมผัส และแนะนำให้ใช้สไตลัส (นิ้วก็ใช้ได้เช่นกัน) หากมี ให้ลองใช้ตัวอย่าง 2d หรือ webgl สำหรับคนอื่นๆ โปรดดูการสาธิตโดย Miguel Casas หนึ่งในวิศวกรที่ใช้ฟีเจอร์นี้ เปิดการสาธิต กดเล่น จากนั้นเลื่อนแถบเลื่อนกลับไปกลับมาแบบสุ่มอย่างรวดเร็ว
ตัวอย่างนี้ใช้คลิปความยาว 1 นาที 21 วินาทีจากภาพยนตร์สั้นเรื่อง Sintel โดย Durian ซึ่งเป็นโปรเจ็กต์ภาพยนตร์เปิดเรื่อง ในตัวอย่างนี้ ภาพยนตร์จะเล่นในองค์ประกอบ <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 อื่นๆ อยู่เหนือองค์ประกอบดังกล่าว
มีได้ 1 ประเภทเท่านั้น
คุณจะเปลี่ยนแอตทริบิวต์บริบทหลังจากเรียกไปยัง canvas.getContext()
ครั้งแรกไม่ได้ ความรู้สึกเช่นนี้มักจะเกิดขึ้นเสมอ แต่การกล่าวซ้ำๆ อาจช่วยให้คุณรู้สึกหงุดหงิดได้หากคุณไม่รู้ตัวหรือลืมไป
ตัวอย่างเช่น สมมติว่าผมได้รับบริบทและระบุอัลฟ่าเป็น "เท็จ" จากนั้นผมเรียก canvas.getContext()
เป็นครั้งที่ 2 ในโค้ดของผมด้วยการตั้งค่าอัลฟ่าเป็น "จริง" ดังที่แสดงด้านล่าง
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 ยังคงเป็นเท็จอยู่ และจะไม่มีการสร้างบริบทที่มีอัลฟ่าเท่ากับ "จริง"
ประเภทแคนวาสที่รองรับ
พารามิเตอร์แรกที่ส่งไปยัง getContext()
คือ contextType
หากคุ้นเคยกับ getContext()
อยู่แล้ว ก็ไม่ต้องสงสัยเลยว่ามีการรองรับบริบทอื่นนอกเหนือจากประเภท "2d" ไหม ตารางด้านล่างแสดงประเภทบริบทที่รองรับ desynchronized
contextType | ออบเจ็กต์ประเภทบริบท |
---|---|
|
|
|
|
|
|
บทสรุป
หากต้องการดูข้อมูลเพิ่มเติม ให้ดูตัวอย่าง นอกเหนือจากตัวอย่างวิดีโอที่อธิบายไปแล้ว ยังมีตัวอย่างที่แสดงทั้งบริบท "2d" และ "webgl" อีกด้วย