לא ניתן להבחין בין טכנולוגיה מתקדמת מספיק לבין קסם. אלא אם הבנתם את זה. קוראים לי תומאס סטיינר ואני עובד בצוות קשרי מפתחים ב-Google. בסיכום הנוכחי שלי בנושא Google I/O אעבור על כמה מממשקי ה-API החדשים של Fugu, ואסביר איך הם משפרים את התהליכים העיקריים של המשתמשים ב-Excalidraw PWA. כך תוכלו לקבל השראה מהרעיונות האלה וליישם אותם באפליקציות שלכם.
איך הגעתי לאגרלה
אני רוצה להתחיל בכתבה. ב-1 בינואר 2020, כריסטופר צ'דו, מהנדס תוכנה ב-Facebook, שלח ציוץ על אפליקציית שרטוט קטנה שהוא התחיל לעבוד עליה. בעזרת הכלי הזה אפשר לשרטט תיבות וחיצים שמרגישים קריקטורה או ציור ביד. למחרת אפשר גם לצייר שלוש נקודות וטקסט, לבחור אובייקטים ולהזיז אותם. ב-3 בינואר האפליקציה קיבלה את השם שלה, Excalidraw, וכמו בכל פרויקט צדדי טוב, קניית שם הדומיין הייתה אחת מהפעולות הראשונות של כריסטופר. עכשיו אפשר להשתמש בצבעים ולייצא את כל הציור כקובץ PNG.
ב-15 בינואר, כריסטופר פרסם פוסט בבלוג שמשך הרבה תשומת לב ב-Twitter, כולל שלי. התחיל הפוסט עם נתונים סטטיסטיים מרשימים:
- 12,000 משתמשים פעילים ייחודיים
- 1,500 כוכבים ב-GitHub
- 26 תורמי תוכן
זה לא רע בכלל לפרויקט שהתחיל לפני שבועיים בלבד. אבל הדבר שבאמת הדהים אותי היה בחלק התחתון של הפוסט. כריסטופר כתב שהוא ניסה הפעם משהו חדש: לתת לכל מי שקיבל בקשת משיכה גישה ללא תנאי. באותו יום שבו קראתי את הפוסט בבלוג, שלחתי בקשה שהוסיפה תמיכה ב-File System Access API כדי לבטל את ההסרה, תיקון בקשת תכונה שמישהו הגיש.
בקשת המשיכה שלי מוזגה יום לאחר מכן, ומשם הייתה לי גישת שמירה מלאה. מיותר לציין שלא השתמשתי לרעה בכוח שלי. וגם אף אחד אחר מ-149 תורמי התוכן עד כה.
כיום, Excalidraw הוא אפליקציה מלאה וזמינה להתקנה, עם תמיכה אופליין, מצב כהה מדהים, וכן יכולת לפתוח ולשמור קבצים הודות ל-File System Access API.
ליפיס מסביר למה הוא מקדיש כל כך הרבה מזמנו
כאן מסתיים הסיפור של "איך הגעתי אל אקסקלידרו", אבל לפני שאחקור כמה מהתכונות המדהימות של Excalidraw, אני שמח להציג את Panayiotis. Panayiotis Lipiridis, באינטרנט שנקראת פשוט lipis, היא התורמת הכי נפוצה ליצירה של Excalidraw. שאלתי את ליפ מה מוטיבציה להשקיע בו כל כך הרבה מזמנו כדי לסחור:
כמו כולם, למדתי על הפרויקט הזה מהציוץ של כריסטופר. התרומה הראשונה שלי הייתה להוסיף את Open Color Library, הצבעים שעדיין נמצאים חלק מ-Excalidraw היום. כשהפרויקט גדל, היו לנו הרבה בקשות. התרומה הגדולה הבאה שלי הייתה לפתח קצה עורפי לאחסון שרטוטים, כדי שהמשתמשים יוכלו לשתף אותם. אבל מה שבאמת מניע אותי לתרום הוא שמי שניסה את Excalidraw צריך למצוא תירוצים כדי להשתמש בה שוב.
אני מסכים לחלוטין עם lipis. מי שניסה את exalidraw צריך למצוא תירוצים כדי להשתמש בה שוב.
ביטול ההסרה בפעולה
עכשיו אני רוצה להראות לך איך אפשר להשתמש בפונקציית אקספרס בפועל. אני לא אמן מעולה, אבל הלוגו של Google I/O פשוט מספיק, אז אני רוצה לנסות. תיבה היא הקו ה-i, קו יכול להיות הקו הנטוי וה-o הוא עיגול. אני לוחץ לחיצה ארוכה על Shift, כך שנוצר עיגול מושלם. אני רוצה להזיז קצת את הקו הנטוי, כדי שהוא ייראה טוב יותר. עכשיו קצת צבע ל-i ול-o. כחול זה טוב. אולי סגנון מילוי אחר? הכול יציב, או שיש בו תקרה מלאה? לא, האצ'ו נראה נהדר. זה לא מושלם, אבל זה הרעיון של Excalidraw, אז אני אשמור את זה.
אני לוחץ על סמל השמירה ומזינים שם קובץ בתיבת הדו-שיח של שמירת הקובץ. ב-Chrome, דפדפן שתומך ב-File System Access API, לא מדובר בהורדה אלא בפעולת שמירה אמיתית, שבה אני יכול לבחור את המיקום ואת השם של הקובץ, ואיפה אוכל לשמור אותם באותו קובץ אם מבצעים עריכות.
אני רוצה לשנות את הלוגו ולהפוך את האות לאדום ל-i. אם אלחץ עכשיו שוב על 'שמור', השינוי יישמר באותו קובץ כמו קודם. להוכחה, אני רוצה למחוק את אזור העריכה ולפתוח מחדש את הקובץ. כמו שאתם רואים, הלוגו בצבע כחול-אדום שהשתנה מופיע שוב.
עבודה עם קבצים
בדפדפנים שלא תומכים כרגע ב-File System Access API, כל פעולת שמירה היא הורדה, כך שכשמבצעים שינויים, מופיעים כמה קבצים עם מספר מצטבר בשם הקובץ שממלא את תיקיית ההורדות. אבל למרות החיסרון הזה, עדיין אוכל לשמור את הקובץ.
פתיחת קבצים
אז מה הסוד? איך הפתיחה והשמירה של הקובץ יפעלו בדפדפנים שונים שתומכים או לא תומכים ב-File System Access API? פתיחת קובץ ב-exalidraw מתבצעת בפונקציה בשם loadFromJSON)(
, שקוראת לפונקציה fileOpen()
.
export const loadFromJSON = async (localAppState: AppState) => {
const blob = await fileOpen({
description: 'Excalidraw files',
extensions: ['.json', '.excalidraw', '.png', '.svg'],
mimeTypes: ['application/json', 'image/png', 'image/svg+xml'],
});
return loadFromBlob(blob, localAppState);
};
הפונקציה fileOpen()
שמגיעה מספרייה קטנה שכתבתי
browser-fs-access, ואנחנו משתמשים בה ב-Excalidraw. הספרייה הזו מספקת גישה למערכת הקבצים דרך File System Access API עם גיבוי מדור קודם, כך שאפשר להשתמש בה בכל דפדפן.
תחילה אראה לך את היישום כאשר יש תמיכה ב-API. לאחר המשא ומתן על סוגי ה-MIME והסיומות המקובלים של הקבצים, החלק המרכזי קורא לפונקציה של File System Access API בשם showOpenFilePicker()
. הפונקציה מחזירה מערך של קבצים או קובץ יחיד, בהתאם לבחירה של כמה קבצים. לאחר מכן, פשוט להניח את נקודת האחיזה של הקובץ לאובייקט הקובץ, כדי שתהיה אפשרות לאחזר אותו שוב.
export default async (options = {}) => {
const accept = {};
// Not shown: deal with extensions and MIME types.
const handleOrHandles = await window.showOpenFilePicker({
types: [
{
description: options.description || '',
accept: accept,
},
],
multiple: options.multiple || false,
});
const files = await Promise.all(handleOrHandles.map(getFileWithHandle));
if (options.multiple) return files;
return files[0];
const getFileWithHandle = async (handle) => {
const file = await handle.getFile();
file.handle = handle;
return file;
};
};
היישום החלופי מסתמך על רכיב input
מסוג "file"
. לאחר המשא ומתן לגבי התוספים וסוגי ה-MIME שיאושרו, השלב הבא הוא ללחוץ באופן פרוגרמטי על רכיב הקלט כדי שתיבת הדו-שיח לפתיחת הקובץ תופיע. בשינוי, כלומר אם המשתמש בחר קובץ אחד או מספר קבצים, ההבטחה מסתיימת.
export default async (options = {}) => {
return new Promise((resolve) => {
const input = document.createElement('input');
input.type = 'file';
const accept = [
...(options.mimeTypes ? options.mimeTypes : []),
options.extensions ? options.extensions : [],
].join();
input.multiple = options.multiple || false;
input.accept = accept || '*/*';
input.addEventListener('change', () => {
resolve(input.multiple ? Array.from(input.files) : input.files[0]);
});
input.click();
});
};
מתבצעת שמירה של הקבצים
עכשיו כדי לבצע שמירה. ב-exalidraw, השמירה מתבצעת בפונקציה שנקראת saveAsJSON()
. בשלב הראשון, המערכת מבצעת סריאליזציה למערך רכיבי Excalidraw ל-JSON, ממירה את ה-JSON ל-blob ואז קוראת לפונקציה fileSave()
. אותה פונקציה מסופקת על ידי הספרייה browser-fs-access.
export const saveAsJSON = async (
elements: readonly ExcalidrawElement[],
appState: AppState,
) => {
const serialized = serializeAsJSON(elements, appState);
const blob = new Blob([serialized], {
type: 'application/vnd.excalidraw+json',
});
const fileHandle = await fileSave(
blob,
{
fileName: appState.name,
description: 'Excalidraw file',
extensions: ['.excalidraw'],
},
appState.fileHandle,
);
return { fileHandle };
};
אני רוצה לבדוק שוב את ההטמעה של דפדפנים עם תמיכה ב-File System Access API. שתי השורות הראשונות נראות קצת מורכבות, אבל כל מה שצריך לעשות הוא לנהל משא ומתן על סוגי ה-MIME ותוספי הקובץ. אם שמרתי בעבר וכבר יש לי כינוי לקובץ, לא צריך להציג תיבת דו-שיח של שמירה. אבל אם זו השמירה הראשונה, תוצג תיבת דו-שיח של קובץ, והאפליקציה תקבל חזרה את הכינוי של הקובץ לשימוש עתידי. לאחר מכן, השאר פשוט כותבים לקובץ, דרך זרם שניתן לכתיבה.
export default async (blob, options = {}, handle = null) => {
options.fileName = options.fileName || 'Untitled';
const accept = {};
// Not shown: deal with extensions and MIME types.
handle =
handle ||
(await window.showSaveFilePicker({
suggestedName: options.fileName,
types: [
{
description: options.description || '',
accept: accept,
},
],
}));
const writable = await handle.createWritable();
await writable.write(blob);
await writable.close();
return handle;
};
התכונה 'שמירה בשם'
אם אחליט להתעלם מכינוי קובץ קיים, אוכל להטמיע את התכונה 'שמירה בשם' כדי ליצור קובץ חדש על סמך קובץ קיים. כדי להציג את זה, צריך לפתוח קובץ קיים, לבצע שינויים מסוימים ואז לא להחליף את הקובץ הקיים, אלא ליצור קובץ חדש באמצעות התכונה 'שמירה בשם'. פעולה זו משאירה את הקובץ המקורי ללא שינוי.
ההטמעה בדפדפנים שלא תומכים ב-File System Access API היא קצרה כי היא כוללת רק רכיב עוגן עם מאפיין download
שהערך שלו הוא שם הקובץ הרצוי, וכתובת URL של blob כערך המאפיין href
.
export default async (blob, options = {}) => {
const a = document.createElement('a');
a.download = options.fileName || 'Untitled';
a.href = URL.createObjectURL(blob);
a.addEventListener('click', () => {
setTimeout(() => URL.revokeObjectURL(a.href), 30 * 1000);
});
a.click();
};
לאחר מכן לוחצים על רכיב העוגן באופן פרוגרמטי. כדי למנוע דליפות זיכרון, צריך לבטל את כתובת ה-URL של ה-blob אחרי השימוש. מכיוון שמדובר בהורדה, לא מוצגת אף תיבת דו-שיח לשמירת קבצים, וכל הקבצים מגיעים לתיקיית Downloads
שמוגדרת כברירת מחדל.
גרירה ושחרור
אחד משילובי המערכת האהובים עליי במחשב הוא גרירה ושחרור. ב-exalidraw, כשמשחררים קובץ .excalidraw
באפליקציה, הוא נפתח מיד ואפשר להתחיל לערוך. בדפדפנים שתומכים ב-File System Access API, אפשר אפילו לשמור את השינויים באופן מיידי. אין צורך לעבור על תיבת דו-שיח של שמירת קובץ, כי נקודת האחיזה הנדרשת של הקובץ הושגה מפעולת הגרירה והשחרור.
הסוד לכך הוא קריאה ל-getAsFileSystemHandle()
בפריט העברת נתונים כאשר יש תמיכה ב-File System Access API. לאחר מכן אני מעביר את כינוי הקובץ הזה ל-loadFromBlob()
, שאולי תזכור מכמה פסקאות למעלה. כל כך הרבה
דברים שאפשר לעשות עם קבצים: פתיחה, שמירה, שמירת יתר, גרירה, שחרור. הקולגה שלי, פיט, ואני תיעדנו את כל הטריקים האלה ועוד במאמר שלנו, כך שתוכלו לעקוב אחריהם במקרה שהכל נעשה מהר מדי.
const file = event.dataTransfer?.files[0];
if (file?.type === 'application/json' || file?.name.endsWith('.excalidraw')) {
this.setState({ isLoading: true });
// Provided by browser-fs-access.
if (supported) {
try {
const item = event.dataTransfer.items[0];
file as any.handle = await item as any
.getAsFileSystemHandle();
} catch (error) {
console.warn(error.name, error.message);
}
}
loadFromBlob(file, this.state).then(({ elements, appState }) =>
// Load from blob
).catch((error) => {
this.setState({ isLoading: false, errorMessage: error.message });
});
}
שיתוף קבצים
שילוב מערכת אחר שפועל כרגע ב-Android, ב-ChromeOS וב-Windows מתבצע באמצעות Web Share Target API. אני נמצאת באפליקציה 'קבצים' בתיקייה Downloads
. אני
מופיעים שני קבצים, אחד מהם עם השם הלא-תיאורי untitled
וחותמת זמן. כדי לבדוק מה
הוא מכיל, אני לוחץ על שלוש הנקודות ואז משתף, ואחת מהאפשרויות שמופיעות היא 'ביטול'. כשמקישים על הסמל, אפשר לראות שהקובץ מכיל שוב את הלוגו של קלט/פלט.
Lipis בגרסה של Electron שהוצאה משימוש
אחד הדברים שאפשר לעשות עם קבצים שעדיין לא דיברתי עליהם הוא להגדיל את ההכנסות מ-doubleclick. בדרך כלל, כשמעלים קובץ ל-"doubleclick" היא שפותחים את האפליקציה שמשויכת לסוג ה-MIME של הקובץ. לדוגמה, עבור .docx
הכתובת תהיה Microsoft Word.
צריך לבטל את הגרסה הקודמת של Electron של האפליקציה שתומכת בשיוכים כאלה של סוגי קבצים. לכן, כשלוחצים לחיצה כפולה על קובץ .excalidraw
, נפתחת האפליקציה Excalidraw Electron. ליפיס, שפגשת כבר בעבר, היה גם היוצר וגם המוציא משימוש של Excalidraw Electron. שאלתי אותו למה לדעתו אפשר להוציא משימוש את גרסת Electron:
אנשים ביקשו להשתמש באפליקציית Electron כבר מההתחלה, בעיקר כי הם רצו לפתוח קבצים באמצעות לחיצה כפולה. המטרה שלנו הייתה גם להוסיף את האפליקציה לחנויות של אפליקציות. במקביל, מישהו הציע ליצור PWA במקום זאת, אז פשוט עשינו את שניהם. למרבה המזל, הצגנו את ממשקי ה-API של Project Fugu, כמו גישה למערכת קבצים, גישה ללוח העריכה, טיפול בקבצים ועוד. בלחיצה אחת תוכלו להתקין את האפליקציה על המחשב או על מכשיר נייד, ללא המשקל הנוסף של אלקטרון. הייתה לנו החלטה קלה להוציא משימוש את גרסת Electron, להתרכז רק באפליקציית האינטרנט ולהפוך אותה ל-PWA הטובה ביותר האפשרית. עכשיו אנחנו יכולים לפרסם אפליקציות PWA בחנות Play וב-Microsoft Store. זה היה מדהים!
אפשר לומר ש-Excalidraw for Electron לא הוצא משימוש כי Electron הוא פגום, לא בכלל, אבל מכיוון שהאינטרנט הפך לטוב מספיק. אהבתי!
טיפול בקבצים
כשאני אומר "האינטרנט הפך לטוב מספיק", זה בזכות תכונות כמו הטיפול הקרוב בקבצים.
זוהי התקנה רגילה של macOS Big Sur. תראו מה קורה כשאני לוחץ לחיצה ימנית על קובץ החרגה. אפשר לפתוח אותו באמצעות Excalidraw, ה-PWA המותקן. כמובן שאפשר להשתמש גם בלחיצה כפולה, אבל ההצגה באמצעות הקלטת מסך היא פחות דרמטית.
איך זה עובד? השלב הראשון הוא להבהיר למערכת ההפעלה את סוגי הקבצים שהאפליקציה שלי יכולה לטפל בהם. אעשה זאת בשדה חדש בשם file_handlers
בקובץ המניפסט של אפליקציית האינטרנט. הערך שלו הוא מערך של אובייקטים עם פעולה ומאפיין accept
. הפעולה קובעת את נתיב כתובת ה-URL שבו מערכת ההפעלה מפעילה את האפליקציה, ואובייקט הקבלה הם צמדי ערכי מפתח של סוגי MIME וסיומות הקובץ המשויכות.
{
"name": "Excalidraw",
"description": "Excalidraw is a whiteboard tool...",
"start_url": "/",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff",
"file_handlers": [
{
"action": "/",
"accept": {
"application/vnd.excalidraw+json": [".excalidraw"]
}
}
]
}
השלב הבא הוא הטיפול בקובץ כאשר האפליקציה מופעלת. זה קורה בממשק launchQueue
, שבו עליי להגדיר צרכן על ידי קריאה ל-setConsumer()
. הפרמטר לפונקציה הזו הוא פונקציה אסינכרונית שמקבלת את launchParams
. לאובייקט launchParams
הזה יש שדה בשם 'קבצים' שמקבל מגוון כינויים של קבצים שאפשר לעבוד איתו. יש לי עניין רק באפשרות הראשונה, ומכינוי הקובץ הזה אני מקבל blob ואז העברתי לחבר הישן שלנו loadFromBlob()
.
if ('launchQueue' in window && 'LaunchParams' in window) {
window as any.launchQueue
.setConsumer(async (launchParams: { files: any[] }) => {
if (!launchParams.files.length) return;
const fileHandle = launchParams.files[0];
const blob: Blob = await fileHandle.getFile();
blob.handle = fileHandle;
loadFromBlob(blob, this.state).then(({ elements, appState }) =>
// Initialize app state.
).catch((error) => {
this.setState({ isLoading: false, errorMessage: error.message });
});
});
}
שוב, אם זה היה מהר מדי, תוכלו לקרוא מידע נוסף על File Treatment API במאמר שלי. אפשר להפעיל את הטיפול בקבצים על ידי הגדרת סימון התכונות הניסיוניות של פלטפורמת האינטרנט. הוא מתוכנן להגיע ב-Chrome בהמשך השנה.
שילוב הלוח
עוד תכונה מגניבה של exalidraw היא השילוב עם הלוח. אני יכול להעתיק את כל הציור שלי או רק חלקים ממנו ללוח, אולי להוסיף סימן מים אם אני רוצה, ואז להדביק אותו באפליקציה אחרת. זוהי גרסת אינטרנט של אפליקציית 'ציור Windows 95', דרך אגב.
הדרך שבה זה עובד פשוטה להפליא. כל מה שדרוש לי הוא הקנבס בתור blob, ואז לכתוב בלוח העריכה על ידי העברת מערך של רכיב אחד עם ClipboardItem
עם ה-blob לפונקציה navigator.clipboard.write()
. למידע נוסף על מה שאפשר לעשות עם ה-API של הלוח, תוכלו לעיין במאמרים של ג'ייסון ושלי.
export const copyCanvasToClipboardAsPng = async (canvas: HTMLCanvasElement) => {
const blob = await canvasToBlob(canvas);
await navigator.clipboard.write([
new window.ClipboardItem({
'image/png': blob,
}),
]);
};
export const canvasToBlob = async (canvas: HTMLCanvasElement): Promise<Blob> => {
return new Promise((resolve, reject) => {
try {
canvas.toBlob((blob) => {
if (!blob) {
return reject(new CanvasError(t('canvasError.canvasTooBig'), 'CANVAS_POSSIBLY_TOO_BIG'));
}
resolve(blob);
});
} catch (error) {
reject(error);
}
});
};
שיתוף פעולה עם אחרים
שיתוף כתובת URL לסשן
ידעת של-expalidraw יש גם מצב שיתופי? אנשים שונים יכולים לעבוד יחד על אותו מסמך. כדי להתחיל סשן חדש, אני לוחץ על לחצן שיתוף הפעולה בזמן אמת ואז מתחיל סשן. אני יכול לשתף עם שותפי העריכה שלי בקלות את כתובת ה-URL של הסשן, הודות ל-Web Share API ששילבה באמצעות Excalidraw.
שיתוף פעולה בזמן אמת
הדמייתי סשן של שיתוף פעולה באופן מקומי על ידי עבודה על הלוגו של Google I/O ב-Pixelbook, בטלפון Pixel 3a וב-iPad Pro. אפשר לראות שהשינויים שביצעתי במכשיר אחד באים לידי ביטוי בכל שאר המכשירים.
אפשר אפילו לראות את כל הסמנים זזים. הסמן של Pixelbook זז בצורה יציבה כי הוא נשלט על ידי משטח מגע, אבל הסמן של טלפון Pixel 3a ועכבר הטאבלט של iPad Pro מדלגים ממקום למקום, כי אני שולט במכשירים האלה על ידי הקשה עם האצבע.
הצגת סטטוסים של שותפי עריכה
כדי לשפר את חוויית שיתוף הפעולה בזמן אמת, אפילו פועלת מערכת לזיהוי חוסר פעילות. הסמן של iPad Pro מציג נקודה ירוקה כאשר משתמשים בו. הנקודה הופכת לשחורה במעבר לכרטיסייה או לאפליקציה אחרת בדפדפן. כשאני באפליקציית Excalidraw אבל פשוט לא עושה כלום, הסמן מציג אותי כלא פעיל ומסמל את שלושת ה-zZZs.
קוראים נלהבים של אתרי החדשות שלנו עשויים לחשוב שזיהוי חוסר פעילות מתממש באמצעות Idle Detection API – הצעה בשלב מוקדם שעבדנו עליה בהקשר של Project Fugu. התראת ספוילר: זה לא. הייתה לנו הטמעה שהתבססה על ה-API הזה ב-Excalidraw, אבל בסופו של דבר החלטנו לבחור גישה מסורתית יותר שמבוססת על מדידה של תנועת המצביעים והחשיפה של הדף.
הגשנו משוב לגבי הסיבה לכך ש-Idle Detection API לא פתר את התרחיש לדוגמה שלנו. כל ממשקי ה-API של Project Fugu מפותחים באופן פתוח, כך שכולם יכולים להצטרף ולשמוע את קולם!
ליפי שמסתירה את מה שמעכב את אקסלגרוף
ועל כך, שאלתי את lipis שאלה אחרונה לגבי מה שלדעתו חסר בפלטפורמת האינטרנט שמסתירה את Excalidraw:
File System Access API נהדר, אבל אתם יודעים מה? רוב הקבצים שחשובים לי כיום נמצאים ב-Dropbox או ב-Google Drive, ולא בדיסק הקשיח. הלוואי ש-File System Access API יכלול שכבת הפשטה שדרכה ספקי מערכות קבצים מרוחקים כמו Dropbox או Google יוכלו לשלב אותה, ושהמפתחים יוכלו להשתמש בה בכתיבת קוד. כך המשתמשים יוכלו להירגע ולדעת שהקבצים שלהם בטוחים בעזרת ספק שירותי הענן שהם סומכים עליו.
אני לגמרי מסכים עם ליפי, גם אני גר בענן. אני מקווה שהתכונה הזו תיושם בקרוב.
מצב אפליקציה עם כרטיסיות
וואו! ראינו הרבה שילובים נהדרים של API ב-Excalidraw. מערכת קבצים, טיפול בקבצים, clipboard, שיתוף באינטרנט ויעד שיתוף באינטרנט. ריכזנו כאן עוד דבר אחד. עד עכשיו יכולתי לערוך מסמך אחד בלבד בכל זמן נתון. לא עוד. זו הפעם הראשונה שאתם נהנים מגרסה מוקדמת של מצב אפליקציה עם כרטיסייה בקטע Excalidraw. כך זה נראה.
יש לי קובץ פתוח ב-expalidraw PWA המותקן שפועל במצב עצמאי. עכשיו אני פותח כרטיסייה חדשה בחלון הנפרד. זו לא כרטיסייה רגילה בדפדפן, אלא כרטיסיית PWA. בכרטיסייה החדשה הזו אפשר לפתוח קובץ משני ולעבוד עליו בנפרד מחלון האפליקציה.
מצב אפליקציה עם כרטיסיות נמצא בשלבים הראשונים שלו, ולא הכול מוגדר בסלע. אם זה מעניין אתכם, כדאי לקרוא על הסטטוס הנוכחי של התכונה הזו במאמר שלי.
סגירה
על מנת לקבל עדכונים בקשר לפיצ'רים האלה ולפיצ'רים אחרים, כדאי לעקוב אחרי כלי המעקב של Fuugu API. אנחנו שמחים מאוד לקדם את האינטרנט ולאפשר לכם לעשות יותר בפלטפורמה. ככה תיכף נשפר את Excalidraw, וזה יהיה לכל האפליקציות המדהימות שתיצרו. מתחילים ליצור באתר excalidraw.com.
אני כבר מחכה לראות כמה מממשקי ה-API שהצגתי היום צצים באפליקציות שלך. שמי תום. אפשר למצוא אותי כ-@toMayac ב-Twitter ובאינטרנט באופן כללי. תודה רבה על הצפייה, ושיהיה לך יום נעים ב-Google I/O.