ความสามารถใหม่ๆ ใน Chrome 65
เปิดใช้ CSS Paint API (หรือที่เรียกว่า “CSS Custom Paint” หรือ “Houdini’s Paint Worklet) โดยค่าเริ่มต้นตั้งแต่ Chrome 65 เป็นต้นไป สิ่งนี้คืออะไร คุณสามารถทำอะไร กับโมเดลนี้ได้บ้าง และทำงานอย่างไร อ่านต่อเลย แล้วจะ...
CSS Paint API ช่วยให้คุณสร้างรูปภาพแบบเป็นโปรแกรมได้ทุกครั้งที่พร็อพเพอร์ตี้ CSS ต้องการรูปภาพ โดยปกติแล้ว พร็อพเพอร์ตี้อย่างเช่น background-image
หรือ border-image
จะใช้กับ url()
เพื่อโหลดไฟล์ภาพ หรือใช้กับฟังก์ชัน CSS ในตัว เช่น linear-gradient()
ซึ่งตอนนี้คุณสามารถใช้ paint(myPainter)
เพื่ออ้างอิงเวิร์กเล็ตชุดสีแทน
การเขียนชิ้นงานสี
หากต้องการกำหนด Worklet Paint ที่ชื่อ myPainter
เราต้องโหลดไฟล์ CSS Paint Worklet โดยใช้ CSS.paintWorklet.addModule('my-paint-worklet.js')
ในไฟล์ดังกล่าว เราใช้ฟังก์ชัน registerPaint
เพื่อลงทะเบียนคลาส Paint Worklet ได้ ดังนี้
class MyPainter {
paint(ctx, geometry, properties) {
// ...
}
}
registerPaint('myPainter', MyPainter);
ภายในการเรียกกลับ paint()
เราสามารถใช้ ctx
ในลักษณะเดียวกับที่ใช้ CanvasRenderingContext2D
อย่างที่เรารู้จักจาก <canvas>
หากคุณรู้วิธีวาดใน <canvas>
คุณสามารถวาดในเวิร์กเล็ตได้! geometry
จะบอกความกว้างและความสูงของภาพพิมพ์แคนวาสที่เราเลือกเอง properties
ซึ่งฉันจะอธิบายภายหลังในบทความนี้
สำหรับตัวอย่างเบื้องต้น เรามาลองเขียนสมุดระบายสีลายตารางหมากรุกและใช้เป็นภาพพื้นหลังของ <textarea>
กัน (ฉันใช้พื้นที่ข้อความเพราะ
ปรับขนาดได้โดยค่าเริ่มต้น):
<!-- index.html -->
<!doctype html>
<style>
textarea {
background-image: paint(checkerboard);
}
</style>
<textarea></textarea>
<script>
CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
paint(ctx, geom, properties) {
// Use `ctx` as if it was a normal canvas
const colors = ['red', 'green', 'blue'];
const size = 32;
for(let y = 0; y < geom.height/size; y++) {
for(let x = 0; x < geom.width/size; x++) {
const color = colors[(x + y) % colors.length];
ctx.beginPath();
ctx.fillStyle = color;
ctx.rect(x * size, y * size, size, size);
ctx.fill();
}
}
}
}
// Register our class under a specific name
registerPaint('checkerboard', CheckerboardPainter);
หากคุณเคยใช้ <canvas>
มาก่อน โค้ดนี้น่าจะดูคุ้นเคย ดู
การสาธิต
สดที่นี่
สิ่งที่แตกต่างจากการใช้ภาพพื้นหลังทั่วไปตรงนี้คือ จะมีการวาดรูปแบบดังกล่าวใหม่ตามคำขอ เมื่อใดก็ตามที่ผู้ใช้ปรับขนาดพื้นที่ข้อความ ซึ่งหมายความว่าภาพพื้นหลังจะมีขนาดใหญ่ตามต้องการเสมอ รวมถึงค่าชดเชยสำหรับจอแสดงผลความหนาแน่นสูง
เยี่ยมไปเลย แต่ก็เป็นภาพนิ่งด้วย เราจะเขียนเวิร์กเล็ตใหม่ ทุกครั้งที่ต้องการรูปแบบเดียวกันแต่มีสี่เหลี่ยมจัตุรัส ขนาดต่างกันไหม คำตอบคือไม่
พารามิเตอร์ของ Worklet
โชคดีที่ Worklet สำหรับ Paint สามารถเข้าถึงพร็อพเพอร์ตี้ CSS อื่นๆ ได้ ซึ่งเป็นที่มาของพารามิเตอร์ properties
เพิ่มเติม การกำหนดแอตทริบิวต์ inputProperties
แบบคงที่ให้กับคลาสจะช่วยให้คุณติดตามการเปลี่ยนแปลงในพร็อพเพอร์ตี้ CSS รวมถึงพร็อพเพอร์ตี้ที่กำหนดเองได้ คุณจะได้รับค่านี้ผ่านพารามิเตอร์ properties
<!-- index.html -->
<!doctype html>
<style>
textarea {
/* The paint worklet subscribes to changes of these custom properties. */
--checkerboard-spacing: 10;
--checkerboard-size: 32;
background-image: paint(checkerboard);
}
</style>
<textarea></textarea>
<script>
CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
// inputProperties returns a list of CSS properties that this paint function gets access to
static get inputProperties() { return ['--checkerboard-spacing', '--checkerboard-size']; }
paint(ctx, geom, properties) {
// Paint worklet uses CSS Typed OM to model the input values.
// As of now, they are mostly wrappers around strings,
// but will be augmented to hold more accessible data over time.
const size = parseInt(properties.get('--checkerboard-size').toString());
const spacing = parseInt(properties.get('--checkerboard-spacing').toString());
const colors = ['red', 'green', 'blue'];
for(let y = 0; y < geom.height/size; y++) {
for(let x = 0; x < geom.width/size; x++) {
ctx.fillStyle = colors[(x + y) % colors.length];
ctx.beginPath();
ctx.rect(x*(size + spacing), y*(size + spacing), size, size);
ctx.fill();
}
}
}
}
registerPaint('checkerboard', CheckerboardPainter);
ตอนนี้ เราสามารถใช้โค้ดเดียวกันสำหรับกระดานหมากรุกทุกประเภทได้ แต่ยิ่งไปกว่านั้น ในตอนนี้เราสามารถไปที่เครื่องมือสำหรับนักพัฒนาเว็บและหาค่าต่างๆ จนกว่าเราจะพบรูปแบบที่เหมาะสม
เบราว์เซอร์ที่ไม่รองรับ Worklet Paint
ในขณะที่เขียน มีเพียง Chrome เท่านั้นที่ติดตั้งใช้งาน Worklet สีได้ แม้ว่าผู้ให้บริการเบราว์เซอร์อื่นๆ ทั้งหมดจะมีสัญญาณเชิงบวก แต่ก็ยังไม่มีความคืบหน้ามากนัก หากต้องการดูข่าวสารล่าสุด โปรดดู Is Houdini Ready Yet? อย่างสม่ำเสมอ ในระหว่างนี้ โปรดใช้การเพิ่มประสิทธิภาพแบบต่อเนื่องเพื่อให้โค้ดทํางานต่อไปแม้ว่าจะไม่รองรับเวิร์กเล็ต Paint ก็ตาม เพื่อให้แน่ใจว่าการทำงานเป็นไปตามที่คาดไว้ คุณจะต้องปรับเปลี่ยนโค้ดใน 2 ที่ ได้แก่ CSS และ JS
การตรวจหาการรองรับ Paint Worklet ใน JS ทำได้โดยตรวจสอบออบเจ็กต์ CSS
ดังนี้
js
if ('paintWorklet' in CSS) {
CSS.paintWorklet.addModule('mystuff.js');
}
สำหรับฝั่ง CSS คุณมี 2 ตัวเลือก คุณใช้ @supports
ได้โดยทำดังนี้
@supports (background: paint(id)) {
/* ... */
}
เคล็ดลับที่กระชับกว่าคือการใช้ข้อเท็จจริงที่ว่า CSS ทำให้เป็นโมฆะ และจะไม่สนใจการประกาศพร็อพเพอร์ตี้ทั้งหมดในภายหลังหากมีฟังก์ชันที่ไม่รู้จัก หากระบุพร็อพเพอร์ตี้ 2 ครั้ง โดยครั้งแรกไม่มี Worklet สี ตามด้วย Worklet สี คุณจะได้รับการเพิ่มประสิทธิภาพแบบต่อเนื่องดังนี้
textarea {
background-image: linear-gradient(0, red, blue);
background-image: paint(myGradient, red, blue);
}
ในเบราว์เซอร์ที่มีการรองรับ Paint Worklet การประกาศครั้งที่ 2 ของ background-image
จะเขียนทับรายการแรก ในเบราว์เซอร์ที่ไม่มีการรองรับ Worklet สำหรับ Paint การประกาศครั้งที่ 2 ไม่ถูกต้องและจะถูกนำออก โดยการประกาศแรกจะมีผล
โพลีฟิลล์สำหรับสี CSS
คุณยังใช้ CSS Paint Polyfill เพื่อการใช้งานหลายอย่างได้ ซึ่งจะเพิ่มการรองรับ CSS Custom Paint และ Paint Worklets ลงในเบราว์เซอร์ที่ทันสมัย
กรณีการใช้งาน
ตัวอย่างการใช้งานสำหรับ Paintlets มีมากมาย บางกรณีก็เห็นได้ชัดเจนกว่าเครื่องมืออื่นๆ หนึ่งในเทคนิคที่ชัดเจนกว่านั้นคือการใช้ Paint Worklet เพื่อลดขนาด DOM บ่อยครั้งที่มีการเพิ่มองค์ประกอบเพื่อสร้างการตกแต่งโดยใช้ CSS ตัวอย่างเช่น ใน Material Design Lite ปุ่มที่มีเอฟเฟกต์ระลอกคลื่นจะมีองค์ประกอบ <span>
เพิ่มเติมอีก 2 รายการเพื่อนำคลื่นมาใช้เอง หากคุณมีปุ่มจำนวนมาก อาจทำให้เพิ่มองค์ประกอบ DOM ได้จำนวนมาก และอาจทำให้ประสิทธิภาพในอุปกรณ์เคลื่อนที่ลดลงได้ หากใช้เอฟเฟกต์ระลอกคลื่นโดยใช้เวิร์กเล็ต Paint แทน จะมีองค์ประกอบเพิ่มเติม 0 รายการและเวิร์กเล็ต Paint 1 รายการ
นอกจากนี้ยังมีฟีเจอร์ที่ปรับแต่งและแยกพารามิเตอร์ได้ง่ายขึ้นอีกด้วย
ข้อดีอีกอย่างหนึ่งของการใช้ Paint Worklet ก็คือ โดยทั่วไปแล้วโซลูชันที่ใช้ Paint Worklet จะมีขนาดเล็กในแง่ของไบต์ แน่นอนว่าต้องมีการแลกเปลี่ยนกัน กล่าวคือ รหัสสีจะทำงานเมื่อขนาดของภาพพิมพ์แคนวาสหรือพารามิเตอร์เปลี่ยนแปลง ดังนั้นหากโค้ดของคุณซับซ้อนและใช้เวลานาน ก็อาจเกิดการกระตุกได้ Chrome กำลังดำเนินการย้าย Paint Worklet ออกจากเทรดหลัก เพื่อให้แม้แต่ไฟล์ Paint ที่ทำงานนานๆ ก็ไม่ส่งผลต่อการตอบสนองของเทรดหลัก
สำหรับผมแล้ว โอกาสที่น่าตื่นเต้นที่สุดคือ Paint Worklet ช่วยให้มีการใช้โพลีฟิลล์อย่างมีประสิทธิภาพสำหรับฟีเจอร์ CSS ที่เบราว์เซอร์ยังไม่มี ตัวอย่างหนึ่งก็คือการใช้ Polyfill การไล่ระดับสีแบบกรวย จนกว่าจะไปถึง Chrome ในเครื่อง อีกตัวอย่างหนึ่งคือในการประชุม CSS เราตัดสินใจว่าตอนนี้คุณมีเส้นขอบหลายสีได้แล้ว ขณะที่การประชุมนี้ดำเนินไป เพื่อนร่วมงานของฉัน Ian Kilpatrick ได้เขียน Polyfill สำหรับลักษณะการทำงานของ CSS ใหม่นี้โดยใช้ Paint Worklet
การคิดนอกกรอบ "กรอบ"
คนส่วนใหญ่เริ่มนึกถึงภาพพื้นหลังและภาพเส้นขอบเมื่อเรียนรู้เกี่ยวกับ Worklet Paint กรณีการใช้งานที่เข้าใจน้อยลงอย่างหนึ่งสำหรับ Paint Worklet คือ mask-image
เพื่อทำให้องค์ประกอบ DOM มีรูปร่างที่กำหนดเอง ดังตัวอย่างต่อไปนี้
diamond
![องค์ประกอบ DOM รูปเพชร](https://developer.chrome.com/static/blog/paintapi/image/a-dom-element-the-shape-5de28c7a5eff9.png?authuser=5&hl=th)
mask-image
ใช้รูปภาพที่มีขนาดเท่ากับองค์ประกอบ พื้นที่ที่รูปภาพมาสก์โปร่งใส องค์ประกอบจะโปร่งใส พื้นที่ที่รูปภาพมาสก์
ทึบแสง องค์ประกอบจะทึบแสง
พร้อมใช้งานแล้วใน Chrome
Worklet สีอยู่ใน Chrome Canary มาระยะหนึ่งแล้ว ด้วย Chrome 65 จะมีการเปิดใช้โดยค่าเริ่มต้น เอาล่ะ เรามาลองสิ่งที่เป็นไปได้ใหม่ๆ ที่ โมเดลระบายสีจะปรากฏขึ้น และแสดงให้เราเห็นว่า คุณทำอะไรบ้าง! หากต้องการแรงบันดาลใจเพิ่มเติม โปรดดูคอลเล็กชันของ Vincent De Oliveira