Spotify הוא שירות הסטרימינג הפופולרי ביותר בעולם למוזיקת אודיו במינויים, והוא שואף כל הזמן לשפר את האופן שבו המשתמשים צורכים תוכן אודיו ווידאו. האפליקציה כוללת ספרייה נרחבת של מוזיקה, פודקאסטים וספרי אודיו, ומשמשת מיליוני משתמשים מדי יום בניידים, במחשבים ובפלטפורמות אחרות.
לאחרונה, Spotify השיקה את נגן המיני של Spotify ללקוחות המנגן במחשב ובאינטרנט. המיני-נגן נועד לספק פקדי הפעלה חיוניים בחלון קטן וקומפקט שמופיע בחלק העליון של המסך, ומאפשר למשתמשים גישה מתמדת ל-Spotify. זו תכונה שביקשו מזמן, ומאפשרת למשתמשים לבצע כמה משימות בו-זמנית בחלונות ובאפליקציות שונים, תוך כדי הנאה מהאמנים, מהפלייליסטים ומהפודקאסטים האהובים עליהם ב-Spotify.
בהמשך מופיעה סקירה מפורטת של הפיתוח של נגן המיני, מה'האק' הראשוני בקנבס ועד לגרסה המתקדמת והנוחה יותר למשתמש, שמבוססת על Document Picture-in-Picture API החדש.
'הטריק של משטח הציור'
הגרסה הראשונית של המיני-נגן הושקתה בשנת 2019 בנגן האינטרנט של Spotify כפרויקט פריצה. המטרה הייתה להשתמש ב-Picture-in-Picture (PiP) API של הדפדפן עבור <video> כדי להציג את עטיפת האלבום בחלון שמוצג תמיד בחלק העליון של המסך. עם זאת, ה-API הזה תוכנן בעיקר לשימוש ברכיבי וידאו, ולא ניתן היה להציג תמונות של עטיפות אלבומים. ב-Spotify עקפו את הבעיה הזו על ידי רינדור של עטיפת האלבום לרכיב בד ובעזרת השיטה HTMLCanvasElement
captureStream()
כדי לקבל אובייקט MediaStream בזמן אמת. לאחר מכן, השידור הזה משמש כמקור לסרטון שמשמש את PiP API. הגישה הזו מבוססת על הדוגמה 'פלייליסט אודיו' ב-Google Chrome.
כדי לקבוע אילו לחצני נגן יופיעו בחלון ה-PiP, Spotify שילבה את הלוח עם מנהלי הפעולות המתאימים שהוגדרו ב-Media Session API. כך המשתמשים קיבלו חלון צף עם עטיפת האלבום ופקדי הנגן, שבאמצעותם הם יכלו לשלוט בהפעלה תוך התמקדות במשימות אחרות.
כך אפשר היה ל-Spotify להציג נגן מיני בסיסי. עם זאת, לגישה הזו היו כמה מגבלות:
- אין תמיכה בכתוביות בסרטונים בחלון של 'תמונה בתוך תמונה'. מאחר ש-Spotify נדרשה להציג כתוביות בכל הסרטונים, היא נאלצה לסגור את חלון ה-PIP ברגע שהסרטון התחיל לפעול.
- פקדי הנגן גלויים רק אם ההפעלה מתבצעת באופן מקומי. Spotify מאפשרת הפעלה מרחוק באמצעות Spotify Connect (ופרוטוקולים אחרים), והיא רוצה שהמשתמשים יוכלו לשלוט בהפעלה הזו גם כן
- אין תמיכה בהתאמה אישית של המראה והתחושה של חלון ה-PiP. Spotify יכולה להציג רק גרפיקה ולהשתמש בפקדי הנגן ש-Chrome מספק, כך שלא ניתן להוסיף את המיתוג של Spotify או פקדים נוספים לנגן.
חוסר השליטה בממשק המשתמש והחוסר ביכולת להוסיף תכונות ספציפיות ל-Spotify (למשל, סימון טראק בלייק) גרמו להם להרגיש שהגישה הזו לא מתאימה ללקוח שלהם למחשב.
התכונה 'תמונה בתוך תמונה' במסמכים: האבולוציה של מיני-נגן
בתחילת 2023, Spotify נודע על העניין המחודש של Google Chrome בהשקת ממשק API חדש שיאפשר להציג תוכן HTML שרירותי בתוך חלון ה-PiP, שנקרא Document Picture-in-Picture API. התפתחות זו הייתה מרגשת ל-Spotify כי היא נתנה לה שליטה מלאה על המראה של חלון ה-PIP. צוות Spotify עבד בשיתוף עם צוות Chrome במהלך התוכנית לניסוי בגרסת המקור כדי לפתח נגן מיני חדש שמבוסס על Document Picture-in-Picture API.
Document PiP API מאפשר לכם לפתוח חלון חדש שנמצא תמיד בחלק העליון של המסך, שאליו תוכלו לצרף רכיבים. מאחר שנגן האינטרנט של Spotify הוא אפליקציית אינטרנט של React, ב-Spotify השתמשו בשיטה createPortal()
של ReactDOM כדי להציג רכיבים מותאמים אישית בחלון ה-PiP מהאפליקציה הראשית, וכך לתת שליטה מלאה על המראה והתכונות של נגן המיני.
ב-Document Picture-in-Picture API החדש טופל גם בבעיות הקודמות של Spotify:
- סרטונים בחלון PiP הם רכיבי וידאו רגילים עם תמיכה מלאה בכתוביות.
- כשיש לכם שליטה מלאה בממשק המשתמש, לחצני הנגן יכולים להופיע גם כשההפעלה מתבצעת מרחוק באמצעות Spotify Connect.
- ב-Spotify הצליחו לשלב את העיצוב ואת אמצעי הבקרה של הנגן, וכך לשפר את חוויית המשתמש.
- הם הצליחו להוסיף תמיכה ב-Document PiP API ללקוח של Spotify למחשב, וכך להציע את נגן המיני למיליונים של משתמשים במחשב.
יצירת חלון 'תמונה בתוך תמונה' באמצעות React
בדוגמה הבאה מוסבר איך להשתמש בתכונה 'תמונה בתוך תמונה' של מסמכים ב-React, בדיוק כמו צוות Spotify. יוצרים שני רכיבי React: MyFeature
ו-PiPContainer
.
הרכיב MyFeature
אחראי לניהול החלון של התמונה בתוך התמונה. הוא יוצר לחצן שמפעיל או משבית את חלון התמונה בתוך תמונה, ויוצר את הרכיב PiPContainer
. הוא גם נרשם לאירוע "pagehide"
של החלון של 'תמונה בתוך תמונה' כדי לעדכן את המצב כשהחלון נסגר.
const MyFeature = () => {
const [pipWindow, setPiPWindow] = useState<Window | null>(
documentPictureInPicture.window
);
const handleClick = useCallback(async () => {
if (pipWindow) {
pipWindow.close();
} else {
const newWindow = await documentPictureInPicture.requestWindow();
setPiPWindow(newWindow);
}
}, [pipWindow]);
useEffect(() => {
const handleWindowClose = (): void => {
setPiPWindow(null);
};
pipWindow?.addEventListener("pagehide", handleWindowClose);
return () => {
pipWindow?.removeEventListener("pagehide", handleWindowClose);
};
}, [pipWindow]);
return (
<>
<button onClick={handleClick}>
{pipWindow ? "Close PiP Window" : "Open PiP Window"}
</button>
<PiPContainer pipWindow={pipWindow}>Hello World 👋!</PiPContainer>
</>
);
};
הרכיב PiPContainer
משתמש בשיטה createPortal() של ReactDOM כדי להציג תוכן בחלון 'תמונה בתוך תמונה'.
type Props = PropsWithChildren<{
pipWindow: Window | null;
}>;
const PiPContainer = ({ pipWindow, children }: Props) => {
useEffect(() => {
if (pipWindow) {
cloneStyles(window.document, pipWindow.document);
}
}, [pipWindow]);
return pipWindow ? createPortal(children, pipWindow.document.body) : null;
};
המאמרים הבאים
ב-Spotify ממשיכים לפתח ולחדש, והם מחויבים לשפר את נגן המיני, ולשפר את התכונות ואת חוויית המשתמש שלו. הצוות עדיין לא יכול להתחייב להוספת תכונות ספציפיות, אבל הוא נלהב מהאפשרויות העתידיות של נגן המיני.
Document Picture-in-Picture API סיפק את הגמישות והשליטה שנדרשו כדי ליצור נגן מיני אינטואיטיבי וידידותי יותר למשתמש. אנחנו מקווים שספקי דפדפנים אחרים יבחינו בהזדמנויות שמציע ממשק ה-API הזה וישקלו להוסיף תמיכה בו. כך Spotify תוכל לספק חוויה עקבית ומשופרת לכל המשתמשים, ללא קשר לדפדפן שבחרתם.
תודות
תודה לכל הצוות ב-Spotify שהיה מעורב בפיתוח של נגן המיני.
בנוסף, אנחנו ב-Spotify רוצים להודות לצוות Google Chrome על שיתוף הפעולה ועל ההתייחסות למשוב של Spotify לגבי Document Picture-in-Picture API.