כדי לתת ל-PWA תחושה שדומה יותר לאפליקציה, אפשר להשתמש באזור של סרגל הכותרת שליד פקדי החלונות.
אם אתם זוכרים את המאמר שלי לגרום ל-PWA להרגיש יותר כמו אפליקציה, אולי אתם זוכרים איך הזכרתי את התאמה אישית של סרגל הכותרת באפליקציה כאסטרטגיה ליצירת חוויה שדומה יותר לאפליקציה. הדוגמה הבאה ממחישה איך זה יכול להיראות כשאפליקציית הפודקאסטים של macOS.
עכשיו, יכול להיות שתתפתו להתנגד לטענה ש-פודקאסטים היא אפליקציית macOS ספציפית לפלטפורמה שלא פועלת בדפדפן, ולכן יכולה לעשות מה שהיא רוצה בלי להפעיל לפי הכללים של הדפדפן. נכון, אבל החדשות הטובות הן שהתכונה 'שכבת-על של פקדי Windows', שהיא הנושא של מאמר זה, מאפשרת לכם בקרוב ליצור ממשקי משתמש דומים ל-PWA.
רכיבי שכבת-על של פקדי החלונות
שכבת-העל של פקדי החלונות מורכבת מארבע תכונות משנה:
- הערך
"window-controls-overlay"
עבור השדה"display_override"
בקובץ המניפסט של אפליקציית אינטרנט. - משתני הסביבה של ה-CSS
titlebar-area-x
,titlebar-area-y
,titlebar-area-width
ו-titlebar-area-height
. - תקינה של מאפיין ה-CSS הקודם
-webkit-app-region
כנכסapp-region
, כדי להגדיר אזורים שניתן לגרור בתוכן אינטרנט. - מנגנון לשליחת שאילתות לגבי האזור לבקרת החלון ולעקיפת האזור הזה באמצעות החבר
windowControlsOverlay
ב-window.navigator
.
מהי שכבת-על של פקדי החלונות
אזור סרגל הכותרת מתייחס למרחב שמשמאל או מימין לפקדי החלונות (כלומר, הלחצנים למזעור, להגדלה, לסגירה וכו') ובדרך כלל הוא מכיל את כותרת האפליקציה. 'חלון בקרה על שכבת-על' מאפשר לאפליקציות Progressive Web App (PWA) לספק תחושה שדומה יותר לאפליקציה על ידי החלפת סרגל הכותרת הקיים ברוחב מלא בשכבת-על קטנה שמכילה את פקדי החלונות. כך המפתחים יכולים להציב תוכן מותאם אישית באזור של שורת הכותרת שבשליטת הדפדפן.
הסטטוס הנוכחי
שלב | סטטוס |
---|---|
1. יצירת הסבר | הושלם |
2. יצירת טיוטה ראשונית של מפרט | הושלם |
3. אוספים משוב וחוזרים על העיצוב | בתהליך |
4. גרסת מקור לניסיון | התשובה מלאה |
5. הפעלה | הושלם (ב-Chromium 104) |
איך משתמשים בשכבת-העל של פקדי החלונות
מתבצעת הוספה של window-controls-overlay
לקובץ המניפסט של אפליקציית האינטרנט
כדי להצטרף לשכבת-העל של פקדי החלונות, Progressive Web App צריך להוסיף את "window-controls-overlay"
בתור החבר הראשי ב-"display_override"
בקובץ המניפסט של אפליקציית האינטרנט:
{
"display_override": ["window-controls-overlay"]
}
שכבת-העל של פקדי החלונות תהיה גלויה רק כאשר כל התנאים הבאים מתקיימים:
- האפליקציה לא נפתחת בדפדפן, אלא בחלון PWA נפרד.
- המניפסט כולל
"display_override": ["window-controls-overlay"]
. (ערכים אחרים מותרים לאחר מכן). - אפליקציית ה-PWA פועלת במערכת הפעלה במחשב.
- המקור הנוכחי תואם למקור שעבורו הותקנה ה-PWA.
התוצאה היא אזור ריק של שורת הכותרת, עם פקדי החלון הרגילים משמאל או מימין, בהתאם למערכת ההפעלה.
העברת תוכן לסרגל הכותרת
עכשיו, כשיש רווח בסרגל הכותרת, אפשר להזיז אליו משהו. עבור המאמר הזה, בניתי PWA של תוכן מומלץ ב-Wikimedia. תכונה שימושית לאפליקציה הזו יכולה להיות חיפוש מילים בכותרות המאמרים. קוד ה-HTML של תכונת החיפוש נראה כך:
<div class="search">
<img src="logo.svg" alt="Wikimedia logo." width="32" height="32" />
<label>
<input type="search" />
Search for words in articles
</label>
</div>
כדי להעביר את div
הזה למעלה לשורת הכותרת, נדרש CSS מסוים:
.search {
/* Make sure the `div` stays there, even when scrolling. */
position: fixed;
/**
* Gradient, because why not. Endless opportunities.
* The gradient ends in `#36c`, which happens to be the app's
* `<meta name="theme-color" content="#36c">`.
*/
background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
/* Use the environment variable for the left anchoring with a fallback. */
left: env(titlebar-area-x, 0);
/* Use the environment variable for the top anchoring with a fallback. */
top: env(titlebar-area-y, 0);
/* Use the environment variable for setting the width with a fallback. */
width: env(titlebar-area-width, 100%);
/* Use the environment variable for setting the height with a fallback. */
height: env(titlebar-area-height, 33px);
}
ניתן לראות את ההשפעה של הקוד הזה בצילום המסך בהמשך. סרגל הכותרת מגיב באופן מלא. כשמשנים את הגודל של חלון ה-PWA, סרגל הכותרת מגיב כאילו הוא מורכב מתוכן HTML רגיל, שהוא למעשה כזה.
קביעה אילו חלקים של סרגל הכותרת ניתנים לגרירה
צילום המסך שלמעלה מרמז שסיימת, אבל עדיין לא סיימת. בחלון ה-PWA אי אפשר יותר לגרור (מלבד אזור קטן מאוד), מכיוון שלחצני החלון אינם אזורי גרירה ושאר סרגל הכותרת כולל את ווידג'ט החיפוש. מתקנים את הבעיה באמצעות מאפיין ה-CSS app-region
עם הערך drag
. במקרה הבטון, אפשר להפוך את כל מה חוץ מהרכיב input
לגרירה.
/* The entire search `div` is draggable… */
.search {
-webkit-app-region: drag;
app-region: drag;
}
/* …except for the `input`. */
input {
-webkit-app-region: no-drag;
app-region: no-drag;
}
כשה-CSS נמצא במקום, המשתמש יכול לגרור את חלון האפליקציה כרגיל על ידי גרירה של ה-div
, ה-img
או label
. רק הרכיב input
הוא אינטראקטיבי כך שאפשר להזין את שאילתת החיפוש.
זיהוי תכונות
כדי לזהות תמיכה בשכבת-על של פקדי חלונות אפשר לבדוק אם יש windowControlsOverlay
:
if ('windowControlsOverlay' in navigator) {
// Window Controls Overlay is supported.
}
שליחת שאילתה לאזור פקדי החלונות באמצעות windowControlsOverlay
בקוד עד עכשיו יש בעיה אחת: בחלק מהפלטפורמות פקדי החלונות נמצאים בצד ימין, ובחלק אחר הם נמצאים בצד שמאל. כדי להחמיר את המצב, תפריט "שלוש הנקודות" של Chrome ישנה גם
את המיקום, בהתאם לפלטפורמה. כלומר, צריך להתאים באופן דינמי את תמונת הרקע ההדרגתית הלינארית כך שתפעל מ-#131313
←maroon
או מ-maroon
←#131313
←maroon
, כדי שהיא תשתלב עם צבע הרקע maroon
של סרגל הכותרת, שנקבע לפי <meta name="theme-color" content="maroon">
. כדי לעשות זאת, אפשר לשלוח שאילתה ל-API getTitlebarAreaRect()
בנכס navigator.windowControlsOverlay
.
if ('windowControlsOverlay' in navigator) {
const { x } = navigator.windowControlsOverlay.getTitlebarAreaRect();
// Window controls are on the right (like on Windows).
// Chrome menu is left of the window controls.
// [ windowControlsOverlay___________________ […] [_] [■] [X] ]
if (x === 0) {
div.classList.add('search-controls-right');
}
// Window controls are on the left (like on macOS).
// Chrome menu is right of the window controls overlay.
// [ [X] [_] [■] ___________________windowControlsOverlay [⋮] ]
else {
div.classList.add('search-controls-left');
}
} else {
// When running in a non-supporting browser tab.
div.classList.add('search-controls-right');
}
במקום להשתמש בתמונת הרקע בכללי ה-CSS של המחלקה .search
(כמו קודם), הקוד שהשתנה משתמש עכשיו בשתי מחלקות שהקוד שלמעלה מגדיר באופן דינמי.
/* For macOS: */
.search-controls-left {
background-image: linear-gradient(90deg, #36c, 45%, #131313, 90%, #36c);
}
/* For Windows: */
.search-controls-right {
background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
}
בדיקה אם שכבת-העל של פקדי החלונות גלויה
שכבת-העל של פקדי החלונות לא תהיה גלויה באזור סרגל הכותרת בכל מצב. באופן טבעי הוא לא יהיה זמין בדפדפנים שלא תומכים בתכונה 'שכבת-על של פקדי חלונות', אבל היא לא תהיה זמינה גם כשה-PWA המדובר יפעל בכרטיסייה. כדי לזהות את המצב הזה, אפשר להריץ שאילתה על המאפיין visible
של windowControlsOverlay
:
if (navigator.windowControlsOverlay.visible) {
// The window controls overlay is visible in the title bar area.
}
לחלופין, אתם יכולים גם להשתמש בשאילתת המדיה display-mode
ב-JavaScript ו/או ב-CSS:
// Create the query list.
const mediaQueryList = window.matchMedia('(display-mode: window-controls-overlay)');
// Define a callback function for the event listener.
function handleDisplayModeChange(mql) {
// React on display mode changes.
}
// Run the display mode change handler once.
handleDisplayChange(mediaQueryList);
// Add the callback function as a listener to the query list.
mediaQueryList.addEventListener('change', handleDisplayModeChange);
@media (display-mode: window-controls-overlay) {
/* React on display mode changes. */
}
קבלת התראות על שינויים בגאומטריה
שאילתה באזור של שכבת-העל של פקדי החלון באמצעות getTitlebarAreaRect()
יכולה להספיק לפעולות חד-פעמיות, כמו הגדרה של תמונת הרקע הנכונה בהתאם למיקום של פקדי החלונות, אבל במקרים אחרים נדרשת שליטה מדוקדקת יותר. לדוגמה, תרחיש אפשרי הוא להתאים את שכבת-העל של פקדי החלונות בהתאם לשטח הזמין ולהוסיף בדיחה ישירות בשכבת-העל של פקד החלון, כשיש מספיק מקום.
כדי לקבל התראה על שינויים בגאומטריה, אפשר להירשם ל-navigator.windowControlsOverlay.ongeometrychange
או להגדיר event listener עבור
geometrychange
האירוע. האירוע הזה יופעל רק כששכבת-העל של פקדי החלונות גלויה, כלומר כשהערך של navigator.windowControlsOverlay.visible
הוא true
.
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
if ('windowControlsOverlay' in navigator) {
navigator.windowControlsOverlay.ongeometrychange = debounce((e) => {
span.hidden = e.titlebarAreaRect.width < 800;
}, 250);
}
במקום להקצות פונקציה ל-ongeometrychange
, אפשר גם להוסיף event listener ל-windowControlsOverlay
כמו שמתואר בהמשך. ב-MDN אפשר לקרוא על ההבדל בין הסוגים.
navigator.windowControlsOverlay.addEventListener(
'geometrychange',
debounce((e) => {
span.hidden = e.titlebarAreaRect.width < 800;
}, 250),
);
תאימות בהפעלה בכרטיסייה ובדפדפנים שאינם תומכים
יש שני מקרים אפשריים:
- מקרה שבו אפליקציה פועלת בדפדפן שתומך בשכבת-על של פקדי החלונות, אבל משתמשים בה בכרטיסייה בדפדפן.
- מקרה שבו אפליקציה פועלת בדפדפן שלא תומך בשכבת-על של פקדי החלונות.
בשני המקרים, כברירת מחדל, ה-HTML שנוצר לשכבת-העל של פקדי החלונות יוצג בתוך השורה, כמו תוכן HTML רגיל, והערכים החלופיים של המשתנים env()
ייכנסו לתוקף עבור המיקום. בדפדפנים תומכים, אפשר גם להחליט לא להציג את
ה-HTML שמיועד לשכבת-העל של פקדי החלונות. לשם כך, בודקים את המאפיין visible
של שכבת-העל, ואם היא מדווחת על false
, ומסתירים את תוכן ה-HTML הזה.
תזכורת: דפדפנים שלא תומכים בתכונה הזו לא יתייחסו בכלל לנכס המניפסט של אפליקציית האינטרנט "display_override"
או לא יזהו את "window-controls-overlay"
, ולכן הם ישתמשו בערך האפשרי הבא בהתאם לשרשרת החלופית, לדוגמה, "standalone"
.
שיקולים בממשק המשתמש
לא מומלץ ליצור תפריט נפתח קלאסי באזור 'שכבת-על של פקדי החלונות', למרות שהוא מפתה. פעולה זו נחשבת להפרה של הנחיות העיצוב ב-macOS, פלטפורמה שבה המשתמשים מצפים לשורת תפריטים (גם סרגלי תפריטים שסופקו על ידי המערכת וגם סרגלי תפריט בהתאמה אישית) בחלק העליון של המסך.
אם האפליקציה שלכם מספקת חוויה במסך מלא, כדאי לשקול היטב אם הגיוני ששכבת-העל של פקדי החלונות תהיה חלק מתצוגת המסך המלא. יכול להיות שתרצו לשנות את הסדר של הפריסה כשהאירוע onfullscreenchange
מופעל.
הדגמה (דמו)
יצרתי הדגמה שאפשר לשחק איתה בדפדפנים תומכים ובדפדפנים שונים שאינם תומכים, ובמצב מותקן ולא מותקן. כדי להשתמש בחוויית שכבת-העל של פקדי החלונות בפועל, תצטרכו להתקין את האפליקציה. למטה תוכלו לראות שני צילומי מסך של מה שצפוי לקרות. קוד המקור של האפליקציה זמין ב-Glitch.
תכונת החיפוש בשכבת-העל של פקדי החלונות פועלת באופן מלא:
שיקולי אבטחה
צוות Chromium תכנן והטמיע את window Controls Overlay API באמצעות עקרונות הליבה שהוגדרו במאמר שליטה בגישה לתכונות מתקדמות של פלטפורמת אינטרנט, כולל בקרת משתמשים, שקיפות וארגונומיה.
זיוף
כשנותנים לאתרים שליטה חלקית בסרגל הכותרת, המפתחים יכולים לזייף תוכן באזור שהיה בעבר אזור מהימן שנשלט על ידי הדפדפן. כרגע, בדפדפני Chromium, המצב העצמאי כולל סרגל כותרת, שבהפעלה הראשונית, מוצג בו הכותרת של דף האינטרנט בצד שמאל ואת מקור הדף מצד ימין (ולאחר מכן הלחצן 'הגדרות ועוד' ופקדי החלונות). אחרי כמה שניות, טקסט המקור ייעלם. אם הדפדפן מוגדר לשפה מימין לשמאל (RTL), הפריסה הזו הופכת כך שטקסט המקור מופיע בצד שמאל. הפעולה הזו פותחת את שכבת-העל של פקדי החלון כדי לזייף את המקור, אם אין מספיק מרווח בין המקור לבין הקצה הימני של שכבת-העל. לדוגמה, ניתן לצרף את המקור "evil.ltd" לאתר מהימן "google.com", ולגרום למשתמשים להאמין שהמקור מהימן. התוכנית היא לשמור את טקסט המקור הזה כדי שהמשתמשים ידעו מהו מקור האפליקציה, ולהבטיח שהוא תואם לציפיות שלהם. בדפדפנים שמוגדרים כ-RTL, צריך להיות מספיק מרווח פנימי מימין לטקסט המקור כדי למנוע מאתר זדוני להוסיף את המקור הלא בטוח עם מקור מהימן.
טביעת אצבע
הפעלה של שכבת-העל של פקדי החלונות והאזורים שאפשר לגרור לא גורמת לבעיות פרטיות משמעותיות, מלבד זיהוי התכונות. עם זאת, בגלל ההבדלים בגדלים ובמיקומים של לחצני השליטה בחלון במערכות ההפעלה, השיטה navigator.
מחזירה DOMRect
שהמיקום והמידות שלה חושפים מידע על מערכת ההפעלה שבה הדפדפן פועל. נכון לעכשיו, מפתחים יכולים כבר לגלות את מערכת ההפעלה מהמחרוזת של סוכן המשתמש, אבל בגלל בעיות שקשורות ליצירה של טביעת אצבע דיגיטלית, מתקיים דיון על הקפאת המחרוזת של UA ואיחוד גרסאות של מערכת ההפעלה. בקהילת הדפדפנים אנחנו משקיעים מאמצים רבים כדי להבין באיזו תדירות הגודל של שכבת-העל של פקדי החלונות משתנה בפלטפורמות שונות. ההנחה הנוכחית היא שהגרסאות האלה יציבות למדי בכל הגרסאות של מערכת ההפעלה, ולכן הן לא יכולות לעזור לתצפית על גרסאות משניות של מערכת ההפעלה. למרות שיכול להיות שמדובר בבעיה של טביעת אצבע דיגיטלית, היא רלוונטית רק לאפליקציות PWA מותקנות שמבוססות על התכונה של סרגל הכותרת בהתאמה אישית, ולא חלה על שימוש כללי בדפדפן. בנוסף, ה-API navigator.
לא יהיה זמין למסגרות iframe שמוטמעות בתוך PWA.
ניווט
אם מנווטים למקור אחר בתוך PWA, הוא יחזור לסרגל הכותרת הנפרד הרגיל, גם אם הוא עומד בקריטריונים שלמעלה ומופעל עם שכבת-העל של פקדי החלונות. מטרת ההגבלה הזו היא לכלול את הסרגל השחור שמופיע במהלך הניווט למקור אחר. אחרי שתחזרו למקור המקורי, המערכת תשתמש שוב בשכבת-העל של פקדי החלונות.
משוב
צוות Chromium רוצה לשמוע על החוויה שלך בשימוש ב-Window Controls Overlay API.
לספר לנו על עיצוב ה-API
האם יש משהו ב-API שלא פועל כמצופה? או האם חסרים שיטות או מאפיינים שאתם צריכים ליישם את הרעיון? יש לכם שאלה או הערה לגבי מודל האבטחה? שלחו בעיה במפרט במאגר GitHub המתאים, או הוסיפו את דעתכם לבעיה קיימת.
דיווח על בעיה בהטמעה
האם מצאת באג בהטמעה של Chromium? או שההטמעה שונה מהמפרט?
דווחו על באג בכתובת new.crbug.com. הקפידו לכלול כמה שיותר פרטים, הוראות פשוטות לשחזור ולהזין UI>Browser>WebAppInstalls
בתיבה רכיבים. גליץ' הוא כלי מעולה לשיתוף גיבויים מהירים וקלים.
הבעת תמיכה ב-API
האם בכוונתך להשתמש ב-Window Controls Overlay API? התמיכה הציבורית שלכם עוזרת לצוות של Chromium לקבוע סדר עדיפויות לתכונות, ומראה לספקי דפדפנים אחרים עד כמה חשוב התמיכה בהן.
עליך לשלוח ציוץ אל @ChromiumDev עם ה-hashtag של #WindowControlsOverlay
ולהסביר לנו איפה ואיך אתם משתמשים בו.
קישורים שימושיים
- הסבר
- טיוטת המפרט
- באג ב-Chromium
- רשומה בסטטוס הפלטפורמה של Chrome
- תיוג ביקורת
- מסמכים קשורים של Microsoft Edge
אישורים
שכבת-העל של פקדי החלונות הוטמעה וסומנה על ידי Amanda Baker מצוות Microsoft Edge. המאמר הזה נכתב על ידי Joe Medley ו-Kenneth Rohde Christiansen. תמונה ראשית (Hero) של זיגמונד ב-UnFlood.