אפשרויות חדשות ב-Chrome 65
CSS Paint API (נקרא גם 'CSS Custom Paint' או 'Houdini's Paintlet) הוא מופעלת כברירת מחדל החל מ-Chrome 65. מה זה? מה אפשר לעשות? יחד איתו? ואיך זה פועל? טוב, ממשיכים לקרוא, נכון...
באמצעות CSS Paint API אפשר ליצור תמונה באופן פרוגרמטי בכל פעם ששירות CSS
מצפה לתמונה. נכסים כמו background-image
או border-image
בדרך כלל משתמשים בהם עם url()
כדי לטעון קובץ תמונה או עם CSS מובנה
לפונקציות כמו linear-gradient()
. במקום להשתמש בהם, אתם יכולים עכשיו להשתמש
paint(myPainter)
כדי להפנות לסביבת עבודה של צבע.
כתיבת worklet של צבע
כדי להגדיר worklet של צבע בשם myPainter
, צריך לטעון צבע CSS
קובץ worklet באמצעות CSS.paintWorklet.addModule('my-paint-worklet.js')
. כאן
אפשר להשתמש בפונקציה registerPaint
כדי לרשום מחלקה של worklet של צבע:
class MyPainter {
paint(ctx, geometry, properties) {
// ...
}
}
registerPaint('myPainter', MyPainter);
בתוך הקריאה החוזרת של paint()
, אפשר להשתמש ב-ctx
באותו אופן שבו
CanvasRenderingContext2D
כמו שאנחנו מכירים מ-<canvas>
. אם אתם יודעים איך
אפשר לצייר ב<canvas>
, ניתן לצייר במשטח עבודה של צבע! geometry
מציין
הרוחב והגובה של הקנבס שעומדים לרשותנו. properties
אני
נסביר בהמשך המאמר הזה.
בדוגמה הבאה, בואו נכתוב worklet של לוח דמקה ונשתמש בו.
כתמונת רקע של <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
למרבה המזל, worklet של צבע יש גישה למאפייני 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 של צבע
בזמן הכתיבה, הוטמעו רק worklet של Chrome. בזמן הם אותות חיוביים מכל ספקי הדפדפנים האחרים, אין התקדמות משמעותית. כדי להתעדכן, מסמנים את התיבה Is Houdini Ready עדיין? באופן קבוע. בינתיים, חשוב להשתמש ב-Progressive כדי שהקוד ימשיך לפעול גם אם אין תמיכה בצבע מודול worklet. כדי לוודא שהכול יפעל כמו שצריך, עליך להתאים את הקוד בשני מקומות: ה-CSS ו-JS.
כדי לזהות תמיכה ב-worklet של צבע ב-JS, צריך לבדוק את האובייקט CSS
:
js
if ('paintWorklet' in CSS) {
CSS.paintWorklet.addModule('mystuff.js');
}
בצד של שירות ה-CSS, יש שתי אפשרויות לכך. אפשר להשתמש ב-@supports
:
@supports (background: paint(id)) {
/* ... */
}
טריק קומפקטי יותר הוא להשתמש בעובדה ששירות CSS מבטל את תוקף המדיניות ולאחר מכן מתעלם מהצהרת מאפיין במלואה אם יש בה פונקציה לא ידועה. אם המיקום מציינים מאפיין פעמיים – תחילה ללא worklet של צבע, ולאחר מכן עם worklet של הצבע — מקבלים שיפור הדרגתי:
textarea {
background-image: linear-gradient(0, red, blue);
background-image: paint(myGradient, red, blue);
}
בדפדפנים עם תמיכה ב-worklet של צבע, ההצהרה השנייה של
background-image
תחליף את הראשונה. בדפדפנים ללא תמיכה
עבור worklet של צבע, ההצהרה השנייה לא חוקית ותימחק,
כך שההצהרה הראשונה תישאר בתוקף.
מילוי פומבי של צבע CSS
לשימושים רבים אפשר גם להשתמש CSS Paint Polyfill, שמוסיפה תמיכה ב-CSS Custom Paint ו-Worklets ב-CSS לדפדפנים מודרניים.
תרחישים לדוגמה
יש תרחישים רבים לדוגמה של לעבודות צבע, חלקם ברורים יותר
אחרים. אחת הדרכים הברורה יותר היא להשתמש בעבודת צבע כדי להקטין את הגודל
של ה-DOM. לעיתים קרובות, אלמנטים נוספים רק כדי ליצור קישוטים
באמצעות CSS. לדוגמה, ב-Material Design Lite, הלחצן
עם אפקט האדווה מכיל 2 רכיבי <span>
נוספים כדי ליישם
להדוף את עצמו. אם יש הרבה לחצנים, הם יכולים להסתכם במספר גדול של לחצנים
של רכיבי DOM שעלולים לפגוע בביצועים בנייד. אם
להטמיע את אפקט האדווה באמצעות worklet של צבע
בסוף תיצרו 0 אלמנטים נוספים ורק עבודת צבע אחת.
בנוסף, יש משהו שקל יותר להתאים אישית
להגדיר את הפרמטרים.
חיסרון נוסף של שימוש ב-worklet של צבע הוא שברוב המקרים, פתרון השימוש ב-worklet של צבע קטן מבחינת בייטים. כמובן, יש וריאציה: קוד הצבע יפעל בכל פעם שהקנבס בגודל או בפרמטרים שונים. לכן אם הקוד מורכב ונדרש זמן רב, הוא עשוי ליצור ג'אנק. ב-Chrome עובדים על העברת עבודות צבע מהשרשור הראשי כדי גם לעבודות צבע ממושכות לא משפיעות על הרספונסיביות של שרשור.
מבחינתי, הלקוח הפוטנציאלי הכי מרגש הוא שעבודת צבע מאפשרת מילוי פוליגונים של תכונות CSS שעדיין לא קיים בדפדפן. דוגמה אחת לכך היא לביצוע פוליגונים להדרגתיות של conic עד נוחתים ב-Chrome באופן טבעי. דוגמה נוספת: בפגישה של שירות ה-CSS, החליט שעכשיו אפשר ליצור כמה צבעי גבולות. בזמן שהפגישה הייתה והקולגה שלי איאן קילפטריק כתב מילוי פוליגונים לשירות ה-CSS החדש באמצעות worklet של צבע.
חשיבה מחוץ לתיבה
רוב האנשים מתחילים לחשוב על תמונות רקע ותמונות שוליים
ללמוד על worklet של צבע. תרחיש שימוש פחות אינטואיטיבי ב-worklet של צבע הוא
mask-image
כדי לגרום לרכיבי DOM להיות צורות שרירותיות. לדוגמה
יהלום:
mask-image
לוקח תמונה בגודל הרכיב. אזורים שבהם
תמונת המסכה שקופה, האלמנט שקוף. אזורים שבהם לבצע את המסכה
התמונה אטומה, הרכיב אטום.
עכשיו ב-Chrome
worklet של צבע קיים ב-Chrome Canary כבר זמן מה. ב-Chrome 65, אפשר מופעלת כברירת מחדל. כדאי לנסות את האפשרויות החדשות ייפתח לכם עומס של צבע, ותראו לנו מה יצרתם. כדי לקבל יותר השראה, כדאי לצפות באוסף של וינסנט דה אוליביירה.