ความเป็นไปได้ใหม่ๆ ใน Chrome 65
CSS Paint API (หรือที่เรียกว่า "การวาดภาพที่กำหนดเองของ CSS" หรือ "เวิร์กเลตการวาดภาพของ Houdini") จะเปิดใช้โดยค่าเริ่มต้นตั้งแต่ Chrome 65 เป็นต้นไป สิ่งนี้คืออะไร คุณใช้ชื่อช่องทำอะไรได้บ้าง ฟีเจอร์นี้ทำงานอย่างไร โปรดอ่านต่อ…
CSS Paint API ช่วยให้คุณสร้างรูปภาพแบบเป็นโปรแกรมได้ทุกครั้งที่พร็อพเพอร์ตี้ CSS คาดหวังรูปภาพ โดยปกติแล้ว พร็อพเพอร์ตี้อย่าง background-image
หรือ border-image
จะใช้งานร่วมกับ url()
เพื่อโหลดไฟล์รูปภาพ หรือกับฟังก์ชันในตัวของ CSS เช่น linear-gradient()
ตอนนี้คุณสามารถใช้ paint(myPainter)
เพื่ออ้างอิงเวิร์กเลตการระบายสีแทน
การเขียนเวิร์กเลตการระบายสี
หากต้องการกำหนดเวิร์กเลตการระบายสีชื่อ myPainter
เราต้องโหลดไฟล์เวิร์กเลตการระบายสี CSS โดยใช้ CSS.paintWorklet.addModule('my-paint-worklet.js')
ในไฟล์นั้น เราสามารถใช้ฟังก์ชัน registerPaint
เพื่อลงทะเบียนคลาสเวิร์กเลตการระบายสี ดังนี้
class MyPainter {
paint(ctx, geometry, properties) {
// ...
}
}
registerPaint('myPainter', MyPainter);
ใน paint()
callback เราสามารถใช้ ctx
ได้เช่นเดียวกับที่ใช้ CanvasRenderingContext2D
จาก <canvas>
หากวาดใน <canvas>
ได้ ก็จะวาดในเวิร์กเลตการวาดได้ geometry
บอกเราเกี่ยวกับความกว้างและความสูงของภาพพิมพ์แคนวาสที่เราใช้ได้ properties
เราจะอธิบายในบทความนี้ในภายหลัง
ตัวอย่างเบื้องต้นคือมาเขียนเวิร์กเลตการระบายสีตารางหมากรุกและใช้เป็นภาพพื้นหลังของ <textarea>
(ฉันใช้ 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>
มาก่อน รหัสนี้น่าจะดูคุ้นเคย ดูการสาธิตแบบเรียลไทม์ได้ที่นี่
ความแตกต่างจากการใช้ภาพพื้นหลังทั่วไปคือ ระบบจะวาดลวดลายอีกครั้งตามต้องการทุกครั้งที่ผู้ใช้ปรับขนาด textarea ซึ่งหมายความว่ารูปภาพพื้นหลังจะมีขนาดตามที่ต้องการเสมอ รวมถึงมีการชดเชยสำหรับจอแสดงผลที่มีความหนาแน่นสูง
เจ๋งดี แต่ค่อนข้างคงที่ เราจะต้องเขียนชิ้นงานใหม่ทุกครั้งที่ต้องการรูปแบบเดียวกันแต่มีสี่เหลี่ยมจัตุรัสขนาดต่างกันไหม คำตอบคือไม่
การกำหนดพารามิเตอร์ของชิ้นงาน
แต่โชคดีที่เวิร์กเลตการวาดสามารถเข้าถึงพร็อพเพอร์ตี้ 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);
ตอนนี้เราใช้รหัสเดียวกันกับตารางหมากรุกทุกประเภทได้แล้ว แต่ที่ดีกว่านั้นคือตอนนี้เราสามารถไปที่เครื่องมือสำหรับนักพัฒนาเว็บและปรับค่าจนกว่าจะเจอลักษณะที่ถูกต้อง
Values API ของ Houdini เป็นอย่างมาก ซึ่งยังต้องดำเนินการบางอย่างก่อนจึงจะพร้อมใช้งานเบราว์เซอร์ที่ไม่รองรับเวิร์กเลตการวาด
ขณะเขียนบทความนี้ มีเพียง Chrome เท่านั้นที่ติดตั้งใช้งานเวิร์กเลตการทาสี แม้ว่าจะมีสัญญาณเชิงบวกจากผู้ให้บริการเบราว์เซอร์รายอื่นๆ ทั้งหมด แต่ก็ยังมีความคืบหน้าไม่มากนัก โปรดติดตามข้อมูลอัปเดตเกี่ยวกับHoudini พร้อมใช้งานหรือยังเป็นประจำ ในระหว่างนี้ โปรดใช้การปรับปรุงแบบค่อยเป็นค่อยไปเพื่อให้โค้ดทำงานต่อไปได้แม้ว่าจะไม่มีการสนับสนุน Paintworklet ก็ตาม คุณต้องปรับโค้ด 2 แห่ง ได้แก่ CSS และ JS เพื่อให้ทุกอย่างทำงานตามที่คาดไว้
คุณสามารถตรวจหาการรองรับเวิร์กเลตการวาดใน JS ได้โดยตรวจสอบออบเจ็กต์ CSS
ดังนี้
js
if ('paintWorklet' in CSS) {
CSS.paintWorklet.addModule('mystuff.js');
}
สำหรับฝั่ง CSS คุณมี 2 ตัวเลือก คุณใช้ @supports
ในกรณีต่อไปนี้ได้
@supports (background: paint(id)) {
/* ... */
}
เคล็ดลับที่กะทัดรัดยิ่งขึ้นคือการใช้ความจริงที่ว่า CSS จะลบล้างและละเว้นการประกาศพร็อพเพอร์ตี้ทั้งหมดในภายหลังหากมีฟังก์ชันที่ไม่รู้จักอยู่ หากคุณระบุพร็อพเพอร์ตี้ 2 ครั้ง โดยครั้งแรกไม่ได้ใช้เวิร์กเลตการทาสี และครั้งที่ 2 ใช้เวิร์กเลตการทาสี คุณจะได้รับการเพิ่มประสิทธิภาพแบบเป็นขั้นๆ ดังนี้
textarea {
background-image: linear-gradient(0, red, blue);
background-image: paint(myGradient, red, blue);
}
ในเบราว์เซอร์ที่รองรับเวิร์กเลตการวาด การประกาศ background-image
ครั้งที่สองจะเขียนทับครั้งแรก ในเบราว์เซอร์ที่ไม่รองรับเวิร์กเลตการวาด ประกาศที่ 2 จะใช้งานไม่ได้และจะถูกทิ้งไป เหลือเพียงประกาศแรกที่มีผล
CSS Paint Polyfill
สำหรับการใช้งานหลายอย่าง คุณยังใช้ CSS Paint Polyfill ได้ด้วย ซึ่งจะเพิ่มการรองรับ Paint Custom CSS และ Paint Worklet ลงในเบราว์เซอร์สมัยใหม่
กรณีการใช้งาน
เวิร์กเลตการวาดมีกรณีการใช้งานหลายกรณี ซึ่งบางกรณีเห็นได้ชัดกว่ากรณีอื่นๆ ตัวอย่างที่เห็นได้ชัดอย่างหนึ่งคือการใช้เวิร์กเลตการวาดเพื่อลดขนาด DOM บ่อยครั้งที่มีการเพิ่มองค์ประกอบเพื่อตกแต่งโดยใช้ CSS เท่านั้น เช่น ใน Material Design Lite ปุ่มที่มีเอฟเฟกต์กระเพื่อมจะมีองค์ประกอบ <span>
เพิ่มเติม 2 รายการเพื่อใช้เอฟเฟกต์กระเพื่อม หากมีปุ่มจำนวนมาก องค์ประกอบ DOM ก็จะเพิ่มมากขึ้นและอาจทําให้ประสิทธิภาพในอุปกรณ์เคลื่อนที่ลดลง หากใช้เอฟเฟกต์กระเพื่อมโดยใช้เวิร์กเลตการระบายสีแทน คุณจะมีองค์ประกอบเพิ่มเติม 0 รายการและมีเวิร์กเลตการระบายสีเพียงรายการเดียว
นอกจากนี้ คุณยังมีสิ่งที่ปรับแต่งและกำหนดพารามิเตอร์ได้ง่ายกว่ามาก
ข้อดีอีกอย่างหนึ่งของการใช้เวิร์กเลตการวาดคือ โซลูชันที่ใช้เวิร์กเลตการวาดมีขนาดเล็กในแง่ของจำนวนไบต์ในสถานการณ์ส่วนใหญ่ แต่ข้อเสียคือ โค้ดการวาดจะทำงานทุกครั้งที่ขนาดของผืนผ้าใบหรือพารามิเตอร์ใดๆ เปลี่ยนแปลง ดังนั้นหากโค้ดมีความซับซ้อนและใช้เวลานาน ก็อาจทำให้เกิดอาการกระตุก Chrome กำลังดำเนินการย้ายเวิร์กเลตการระบายสีออกจากเธรดหลักเพื่อให้เวิร์กเลตการระบายสีที่ทำงานเป็นเวลานานไม่ส่งผลต่อความรวดเร็วในการตอบสนองของเธรดหลัก
โอกาสที่น่าตื่นเต้นที่สุดสำหรับเราคือเวิร์กเลตการวาดภาพช่วยให้สามารถพ็อลีฟีลฟีเจอร์ CSS ที่เบราว์เซอร์ยังไม่มีได้อย่างมีประสิทธิภาพ ตัวอย่างหนึ่งคือ การใช้การเติมเต็ม conic gradients จนกว่าฟีเจอร์ดังกล่าวจะพร้อมใช้งานใน Chrome โดยค่าเริ่มต้น อีกตัวอย่างหนึ่งคือ ในการประชุม CSS ได้มีการตัดสินใจว่าตอนนี้คุณจะมีเส้นขอบหลายสีได้ ขณะที่เรากำลังประชุมอยู่นี้ เพื่อนร่วมงานของฉัน Ian Kilpatrick ได้เขียน polyfill สำหรับลักษณะการทำงาน CSS ใหม่นี้โดยใช้เวิร์กเลตการวาด
การคิดนอกกรอบ
คนส่วนใหญ่จะเริ่มคิดถึงภาพพื้นหลังและภาพขอบเมื่อได้เรียนรู้เกี่ยวกับเวิร์กเลตการระบายสี Use Case ที่ไม่ค่อยใช้งานง่ายอย่างหนึ่งสำหรับเวิร์กเลตการระบายสีคือ
mask-image
ทำให้องค์ประกอบ DOM มีรูปร่างตามต้องการ ตัวอย่างเช่น เพชร
mask-image
ใช้รูปภาพขนาดเท่ากับองค์ประกอบ องค์ประกอบจะโปร่งใสในพื้นที่ที่รูปภาพมาสก์โปร่งใส พื้นที่ที่รูปภาพมาสก์ทึบแสง องค์ประกอบจะทึบแสง
พร้อมให้ใช้งานใน Chrome แล้ว
เวิร์กเลตการวาดภาพมีอยู่ใน Chrome Canary มาระยะหนึ่งแล้ว ใน Chrome 65 ฟีเจอร์นี้จะเปิดใช้โดยค่าเริ่มต้น ลองใช้โอกาสใหม่ๆ ของฟีเจอร์วาดภาพนี้และแสดงให้เราเห็นสิ่งที่คุณสร้าง ดูแรงบันดาลใจเพิ่มเติมได้ในคอลเล็กชันของ Vincent De Oliveira