หลีกเลี่ยงการทาสีที่ไม่จำเป็น

การวาดองค์ประกอบสำหรับเว็บไซต์หรือแอปพลิเคชันอาจทำให้ต้องเสียค่าใช้จ่ายสูงมาก และอาจส่งผลเสียต่อประสิทธิภาพรันไทม์ บทความนี้จะอธิบายคร่าวๆ เกี่ยวกับสิ่งที่อาจทริกเกอร์การวาดภาพในเบราว์เซอร์ และวิธีป้องกันไม่ให้เกิดการวาดภาพที่ไม่จำเป็น

ภาพวาด: ทัวร์ชมแบบย่อ

งานหลักอย่างหนึ่งที่เบราว์เซอร์ต้องทําคือการแปลง DOM และ CSS เป็นพิกเซลบนหน้าจอ ซึ่งทําผ่านกระบวนการที่ซับซ้อนพอสมควร โดยจะเริ่มด้วยการอ่านมาร์กอัป จากนั้นจะสร้างต้นไม้ DOM การดำเนินการจะคล้ายกับ CSS และสร้าง CSSOM จากการดำเนินการดังกล่าว จากนั้นระบบจะรวม DOM เข้ากับ CSSOM และในที่สุดเราก็จะได้โครงสร้างที่จะเริ่มวาดพิกเซลได้

กระบวนการวาดภาพก็น่าสนใจ ใน Chrome ต้นไม้ DOM และ CSS ที่รวมกันจะได้รับการแรสเตอร์โดยซอฟต์แวร์บางอย่างที่เรียกว่า Skia หากคุณเคยเล่นกับองค์ประกอบ canvas มาก่อน API ของ Skia จะดูคุ้นเคยมาก มีฟังก์ชันสไตล์ moveTo และ lineTo มากมาย รวมถึงฟังก์ชันขั้นสูงอีกมากมาย โดยพื้นฐานแล้ว องค์ประกอบทั้งหมดที่ต้องวาดจะได้รับการกลั่นให้เป็นคอลเล็กชันการเรียกใช้ Skia ที่ดำเนินการได้ และเอาต์พุตคือบิตแมปจำนวนมาก ระบบจะอัปโหลดบิตแมปเหล่านี้ไปยัง GPU และ GPU จะช่วยจัดวางองค์ประกอบเข้าด้วยกันเพื่อให้ได้ภาพสุดท้ายบนหน้าจอ

DOM เป็นพิกเซล

สิ่งที่ควรทราบคือปริมาณงานของ Skia จะได้รับผลกระทบโดยตรงจากสไตล์ที่คุณใช้กับองค์ประกอบ หากคุณใช้สไตล์ที่มีอัลกอริทึมที่ซับซ้อน Skia จะต้องทำงานมากขึ้น Colt McAnlis ได้เขียนบทความเกี่ยวกับวิธีที่ CSS ส่งผลต่อน้ำหนักการแสดงผลของหน้าเว็บ คุณจึงควรอ่านบทความดังกล่าวเพื่อรับข้อมูลเชิงลึกเพิ่มเติม

อย่างไรก็ตาม การดำเนินการเพนต์ต้องใช้เวลา และหากไม่ลดจำนวนลง เราจะใช้งบประมาณเฟรมประมาณ 16 มิลลิวินาทีเกิน ผู้ใช้จะเห็นว่าเฟรมขาดหายไปและคิดว่าแอปกระตุก ซึ่งท้ายที่สุดแล้วจะส่งผลเสียต่อประสบการณ์ของผู้ใช้แอป เราไม่อยากให้เกิดเหตุการณ์นี้ขึ้นเลย ดังนั้นเรามาลองดูกันว่าสิ่งใดบ้างที่ทำให้ต้องมีการวาดภาพ และเราจะทำอย่างไรได้บ้าง

การเลื่อน

เมื่อคุณเลื่อนขึ้นหรือลงในเบราว์เซอร์ เบราว์เซอร์จะต้องวาดเนื้อหาใหม่ก่อนที่จะปรากฏบนหน้าจอ ในกรณีนี้ พื้นที่ที่จะวาดจะมีขนาดเล็ก แต่ถึงอย่างนั้น องค์ประกอบที่ต้องวาดก็อาจมีการใช้สไตล์ที่ซับซ้อน ดังนั้น การที่คุณต้องทาสีพื้นที่เล็กๆ ไม่ได้หมายความว่างานจะเสร็จเร็ว

หากต้องการดูว่าระบบกำลังวาดภาพพื้นที่ใดอยู่ คุณสามารถใช้ฟีเจอร์ "แสดงสี่เหลี่ยมผืนผ้าของสี" ในเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของ Chrome (เพียงกดไอคอนรูปเฟืองเล็กๆ ที่มุมขวาล่าง) จากนั้นเมื่อเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่ ให้โต้ตอบกับหน้าเว็บ แล้วคุณจะเห็นสี่เหลี่ยมผืนผ้ากะพริบแสดงตําแหน่งและเวลาที่ Chrome วาดส่วนหนึ่งของหน้าเว็บ

แสดงสี่เหลี่ยมผืนผ้าในการแสดงผลในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
แสดงสี่เหลี่ยมผืนผ้าในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome

ประสิทธิภาพการเลื่อนเป็นปัจจัยสําคัญต่อความสําเร็จของเว็บไซต์ ผู้ใช้จะสังเกตได้ทันทีเมื่อเว็บไซต์หรือแอปพลิเคชันเลื่อนไม่ลื่นไหลและจะไม่ชอบ เราจึงมีผลประโยชน์ในการรักษาน้ำหนักของงานเพนต์ให้เบาในระหว่างการเลื่อนเพื่อให้ผู้ใช้ไม่เห็นภาพกระตุก

ก่อนหน้านี้เราได้เขียนบทความเกี่ยวกับประสิทธิภาพการเลื่อนไว้แล้ว โปรดอ่านบทความดังกล่าวหากต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับประสิทธิภาพการเลื่อนที่เฉพาะเจาะจง

การโต้ตอบ

การโต้ตอบเป็นอีกสาเหตุหนึ่งของการวาดภาพ เช่น การวางเมาส์เหนือ การคลิก การแตะ การลาก เมื่อใดก็ตามที่ผู้ใช้ดำเนินการโต้ตอบอย่างใดอย่างหนึ่ง เช่น การวางเมาส์เหนือ Chrome จะต้องวาดองค์ประกอบที่ได้รับผลกระทบอีกครั้ง และเช่นเดียวกับการเลื่อน หากต้องมีการวาดภาพขนาดใหญ่และซับซ้อน อัตราเฟรมก็จะลดลง

ทุกคนต้องการภาพเคลื่อนไหวที่ราบรื่นและน่าดึงดูดในการโต้ตอบ ดังนั้นเราจะต้องดูว่าสไตล์ที่เปลี่ยนแปลงในภาพเคลื่อนไหวทำให้เราเสียเวลามากเกินไปหรือไม่

ชุดค่าผสมที่ไม่เหมาะสม

การสาธิตที่ใช้สีราคาแพง
การสาธิตที่ใช้สีราคาแพง

จะเกิดอะไรขึ้นหากฉันเลื่อนและบังเอิญเลื่อนเมาส์ไปพร้อมๆ กัน ฉันอาจโต้ตอบกับองค์ประกอบโดยไม่ได้ตั้งใจขณะเลื่อนผ่านองค์ประกอบนั้นๆ ซึ่งจะทริกเกอร์การทาสีที่มีราคาแพง ซึ่งอาจทำให้ใช้เฟรมเกินงบประมาณประมาณ 16.7 มิลลิวินาที (เวลาที่เราต้องอยู่ต่ำกว่านั้นเพื่อให้ได้ 60 เฟรมต่อวินาที) เราได้สร้างการสาธิตเพื่อแสดงให้คุณเห็นถึงสิ่งที่เราหมายถึง เราหวังว่าเมื่อเลื่อนและเลื่อนเมาส์ คุณจะเห็นเอฟเฟกต์การวางเมาส์เหนือรายการทำงาน แต่มาดูกันว่าเครื่องมือสำหรับนักพัฒนาเว็บของ Chrome แสดงผลอย่างไร

เครื่องมือสําหรับนักพัฒนาเว็บของ Chrome แสดงเฟรมที่มีราคาแพง
เครื่องมือสำหรับนักพัฒนาเว็บของ Chrome แสดงเฟรมที่มีราคาแพง

ในรูปภาพด้านบน คุณจะเห็นได้ว่าเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์กำลังบันทึกงานเพนต์เมื่อฉันวางเมาส์เหนือบล็อกใดบล็อกหนึ่ง เราใช้สไตล์ที่หนักมากในเดโมเพื่อให้เห็นภาพชัดเจน จึงใช้เฟรมมากกว่าหรือเท่ากับงบประมาณเฟรมในบางครั้ง สิ่งสุดท้ายที่เราไม่ต้องการคือต้องทำการทาสีนี้โดยไม่จำเป็น และโดยเฉพาะอย่างยิ่งในระหว่างการเลื่อนขณะที่มีงานอื่นๆ ต้องทำ

เราจะหยุดปัญหานี้ได้อย่างไร วิธีการแก้ไขนั้นง่ายมาก เคล็ดลับคือแนบตัวแฮนเดิล scroll ที่จะปิดใช้เอฟเฟกต์การวางเมาส์เหนือ และตั้งตัวจับเวลาเพื่อเปิดใช้เอฟเฟกต์อีกครั้ง ซึ่งหมายความว่าเรารับประกันว่าเมื่อคุณเลื่อนดู เราจะไม่จําเป็นต้องใช้การวาดภาพการโต้ตอบที่มีราคาแพง เมื่อคุณหยุดใช้ไปนานพอแล้ว เราจึงคิดว่าคุณเปิดใช้อีกครั้งได้

โค้ดมีดังนี้

// Used to track the enabling of hover effects
var enableTimer = 0;

/*
 * Listen for a scroll and use that to remove
 * the possibility of hover effects
 */
window.addEventListener('scroll', function() {
  clearTimeout(enableTimer);
  removeHoverClass();

  // enable after 1 second, choose your own value here!
  enableTimer = setTimeout(addHoverClass, 1000);
}, false);

/**
 * Removes the hover class from the body. Hover styles
 * are reliant on this class being present
 */
function removeHoverClass() {
  document.body.classList.remove('hover');
}

/**
 * Adds the hover class to the body. Hover styles
 * are reliant on this class being present
 */
function addHoverClass() {
  document.body.classList.add('hover');
}

ดังที่คุณเห็น เราใช้คลาสในเนื้อหาเพื่อติดตามว่า "อนุญาต" เอฟเฟกต์การโฮเวอร์หรือไม่ และสไตล์พื้นฐานต้องอาศัยคลาสนี้

/* Expect the hover class to be on the body
 before doing any hover effects */
.hover .block:hover {
 
}

เท่านี้ก็เรียบร้อย

บทสรุป

ประสิทธิภาพการแสดงผลเป็นสิ่งสำคัญที่จะทำให้ผู้ใช้เพลิดเพลินกับแอปพลิเคชันของคุณ และคุณควรพยายามทำให้ปริมาณงานของ Paint ต่ำกว่า 16 มิลลิวินาทีเสมอ คุณควรผสานรวมโดยใช้ DevTools ตลอดกระบวนการพัฒนาเพื่อช่วยระบุและแก้ไขปัญหาคอขวดที่เกิดขึ้น

การโต้ตอบโดยไม่ตั้งใจ โดยเฉพาะกับองค์ประกอบที่มีการใช้สีมากอาจทำให้เสียค่าใช้จ่ายสูงและทำให้ประสิทธิภาพการแสดงผลลดลง อย่างที่คุณเห็น เราใช้โค้ดเพียงเล็กน้อยเพื่อแก้ไขปัญหานี้ได้

ลองดูเว็บไซต์และแอปพลิเคชันของคุณว่าควรได้รับการปกป้องสีเล็กน้อยไหม