เทคโนโลยีขั้นสูงมากพอจะแยกไม่ออกจากเวทมนตร์ เว้นแต่คุณจะเข้าใจ ผมชื่อ Thomas Steiner ทำงานในฝ่ายนักพัฒนาซอฟต์แวร์สัมพันธ์ที่ Google และในการเขียนการบรรยายของ Google I/O ครั้งนี้ เราจะพูดถึง Fugu API ใหม่ๆ บางส่วนและวิธีที่ API เหล่านี้ปรับปรุงเส้นทางของผู้ใช้หลักใน Excalidraw PWA เพื่อให้คุณได้แรงบันดาลใจจากไอเดียเหล่านี้และนำไปใช้กับแอปของคุณเอง
เหตุผลที่ฉันเลือก Excalidraw
ฉันอยากเริ่มจากเรื่องราว ในวันที่ 1 มกราคม 2020 Christopher Chedeau วิศวกรซอฟต์แวร์ของ Facebook ได้ทวีตเกี่ยวกับแอปวาดภาพเล็กๆ ที่เขาเริ่มพัฒนา เครื่องมือนี้ช่วยให้คุณวาดกล่องและลูกศรให้ดูเป็นการ์ตูนและวาดด้วยมือได้ ในวันถัดไป คุณยังวาดรูปวงรีและข้อความ รวมถึงเลือกวัตถุและย้ายไปรอบๆ ได้ด้วย ในวันที่ 3 มกราคม แอปได้รับชื่อว่า Excalidraw และเช่นเดียวกับโปรเจ็กต์เสริมที่ดีทุกโปรเจ็กต์ การซื้อชื่อโดเมนเป็นหนึ่งในสิ่งที่ Christopher ต้องทำเป็นอันดับแรก ตอนนี้คุณใช้สีและส่งออกภาพวาดทั้งภาพเป็นไฟล์ PNG ได้แล้ว
ในวันที่ 15 มกราคม Christopher ได้เผยแพร่บล็อกโพสต์ที่ดึงดูดความสนใจอย่างมากบน Twitter รวมถึงความสนใจจากเรา โพสต์เริ่มด้วยสถิติที่น่าประทับใจ:
- จำนวนผู้ใช้ที่ใช้งานอยู่ที่ไม่ซ้ำกัน 1.2 หมื่นคน
- 1.5 พันดาวบน GitHub
- ผู้มีส่วนร่วม 26 คน
โปรเจ็กต์ที่เริ่มต้นเมื่อ 2 สัปดาห์ที่แล้วไม่ได้เลวร้ายอะไรเลย แต่สิ่งที่ดึงดูดความสนใจของฉันจริงๆ คือเนื้อหาที่อยู่ด้านล่างของโพสต์ คณินทราเขียนว่าเขาลองทำสิ่งใหม่ๆ ครั้งนี้ นั่นคือการให้ทุกคนที่ส่งคำขอดึงคำขอเข้าถึงแบบมีเงื่อนไขแบบไม่มีเงื่อนไข ในวันเดียวกันกับการอ่านบล็อกโพสต์ เรามีคำขอดึงที่เพิ่มการรองรับ File System Access API ลงใน Excalidraw เพื่อแก้ไขคำขอฟีเจอร์ที่ผู้ใช้ส่งเข้ามา
ระบบผสานคำขอพุลของฉันไว้ 1 วันต่อมา และนับจากนั้น ฉันก็มีสิทธิ์เข้าถึงแบบคอมมิตทั้งหมด ไม่ต้องบอกก็รู้ว่าฉันไม่ได้ใช้พลังของตัวเอง และจนถึงตอนนี้ก็ไม่มีใครจากผู้ร่วมให้ข้อมูล 149 คนเลย
ปัจจุบัน Excalidraw เป็น Progressive Web App แบบสมบูรณ์ที่ติดตั้งได้ พร้อมการรองรับแบบออฟไลน์ โหมดมืดที่น่าทึ่ง และเปิดและบันทึกไฟล์ได้ด้วย File System Access API
Lipis พูดถึงเหตุผลที่เขาทุ่มเทเวลาให้กับ Excalidraw เป็นอย่างมาก
เรื่องราว "เส้นทางที่ฉันมาสู่ Excalidraw" จบลงแล้ว แต่ก่อนจะเจาะลึกฟีเจอร์อันน่าทึ่งของ Excalidraw เราขอแนะนำ Panayiotis พานายาอิโอทิส ลิปิริดิส ผู้ใช้อินเทอร์เน็ตหรือที่รู้จักกันในชื่อ lipis เป็นผู้มีส่วนเกี่ยวข้องกับ Excalidraw มากที่สุด เราถาม lipis ว่าอะไรคือแรงจูงใจที่ทำให้เขาทุ่มเทเวลาให้กับ Excalidraw มากมายขนาดนี้
เช่นเดียวกับคนอื่นๆ ฉันก็ได้เรียนรู้เกี่ยวกับโปรเจ็กต์นี้จากทวีตของ Christopher การมีส่วนร่วมครั้งแรกของผมคือการเพิ่มไลบรารี Open Color ซึ่งเป็นสีที่ยังคงเป็นส่วนหนึ่งของ Excalidraw ในปัจจุบัน เมื่อโปรเจ็กต์เติบโตขึ้นและเราได้รับคำขอจำนวนมาก สิ่งที่ฉันต้องทำต่อไปคือสร้างแบ็กเอนด์สำหรับจัดเก็บภาพวาดเพื่อให้ผู้ใช้แชร์ภาพวาดได้ แต่สิ่งที่กระตุ้นฉันให้มีส่วนร่วมได้อย่างแท้จริงคือ ใครก็ตามที่ลองใช้ Excalidraw จะมองหาข้อแก้ตัวเพื่อนำมาใช้อีกครั้ง
เห็นด้วยอย่างยิ่งกับ lipis ใครก็ตามที่เคยลองใช้ Excalidraw จะต้องหาข้ออ้างเพื่อใช้แอปนี้อีกครั้ง
การทำงานของ Excalidraw
ตอนนี้เราขอแสดงให้คุณเห็นวิธีใช้ Excalidraw ในทางปฏิบัติ เราไม่ใช่ศิลปินที่เก่ง แต่โลโก้ Google I/O นั้นเรียบง่ายพอ เราจึงขอลองวาดดู ช่องคือตัว "i" เส้นอาจเป็นเครื่องหมายทับ และ "o" คือวงกลม ฉันกด Shift ค้างไว้เพื่อให้ได้วงกลมที่สมบูรณ์แบบ ผมจะลากเครื่องหมายทับเล็กน้อย เพื่อให้ดูดีขึ้น ตอนนี้ให้ใส่สีใน "i" และ "o" สีน้ำเงินคือดี อาจเป็นรูปแบบการเติมแบบอื่น ทั้งหมดเป็นแบบแข็งหรือครอสฮอต ไม่ เส้นแรเงาดูดีมาก อาจจะยังไม่สมบูรณ์แบบ แต่นี่เป็นแนวคิดของ Excalidraw ผมจึงจะบันทึกไว้
ฉันคลิกไอคอนบันทึกแล้วป้อนชื่อไฟล์ในกล่องโต้ตอบบันทึกไฟล์ ใน Chrome ซึ่งเป็นเบราว์เซอร์ที่รองรับ File System Access API การดำเนินการนี้ไม่ใช่การดาวน์โหลด แต่เป็นการดำเนินการบันทึกจริง ซึ่งฉันสามารถเลือกตำแหน่งและชื่อไฟล์ได้ และหากต้องการแก้ไข ก็บันทึกลงในไฟล์เดียวกันได้
เราขอเปลี่ยนโลโก้และทำให้ "i" เป็นสีแดง ถ้าคลิก "บันทึก" อีกครั้ง ระบบจะบันทึกการแก้ไข ลงในไฟล์เดิม เพื่อเป็นการพิสูจน์ เราขอล้างผ้าใบและเปิดไฟล์อีกครั้ง คุณจะเห็นว่าโลโก้ สีแดงน้ำเงินที่ปรับแล้วจะกลับมาปรากฏอีกครั้ง
การทำงานกับไฟล์
ในเบราว์เซอร์ที่ไม่รองรับ File System Access API ในปัจจุบัน การดำเนินการบันทึกแต่ละครั้งจะเป็นการดาวน์โหลด ดังนั้นเมื่อฉันทําการเปลี่ยนแปลง ฉันจึงพบไฟล์หลายไฟล์ที่มีตัวเลขเพิ่มขึ้นในชื่อไฟล์ที่เต็มโฟลเดอร์ "ดาวน์โหลด" แต่ถึงอย่างนั้น ฉันก็ยังสามารถบันทึกไฟล์ได้
การเปิดไฟล์
เคล็ดลับคืออะไร การเปิดและบันทึกจะทำงานอย่างไรในเบราว์เซอร์ต่างๆ ที่อาจรองรับหรือไม่รองรับ File System Access API การเปิดไฟล์ใน Excalidraw เกิดขึ้นในฟังก์ชันที่ชื่อ
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 ซึ่งเราใช้ใน Excaliburaw ไลบรารีนี้ให้การเข้าถึงระบบไฟล์ผ่าน File System Access API พร้อมกับไฟล์สำรองแบบเดิมเพื่อให้ใช้ได้ในเบราว์เซอร์ใดก็ได้
ก่อนอื่น เราขอแสดงการใช้งานเมื่อระบบรองรับ API หลังจากเจรจาประเภท MIME และนามสกุลไฟล์ที่ยอมรับแล้ว หัวใจสำคัญคือการเรียกใช้ฟังก์ชัน showOpenFilePicker()
ของ File System Access API ฟังก์ชันนี้จะแสดงผลอาร์เรย์ของไฟล์หรือไฟล์เดียว โดยขึ้นอยู่กับว่ามีการเลือกหลายไฟล์หรือไม่ ขั้นตอนสุดท้ายคือใส่ตัวแฮนเดิลไฟล์ในออบเจ็กต์ไฟล์เพื่อให้เรียกข้อมูลไฟล์อีกครั้งได้
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();
});
};
กำลังบันทึกไฟล์
มาเริ่มบันทึกกัน ใน Excalidraw การบันทึกจะเกิดขึ้นในฟังก์ชันที่เรียกว่า 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();
};
จากนั้นระบบจะคลิกองค์ประกอบแอตทริบิวต์ "a" โดยใช้โปรแกรม เพื่อป้องกันไม่ให้หน่วยความจำรั่วไหล ต้องเพิกถอน URL ของ Blob หลังการใช้งาน เนื่องจากนี่เป็นเพียงการดาวน์โหลด ระบบจะไม่แสดงกล่องโต้ตอบการบันทึกไฟล์และไฟล์ทั้งหมดจะอยู่ในโฟลเดอร์ Downloads
เริ่มต้น
ลากและวาง
หนึ่งในการผสานรวมระบบที่ฉันใช้บนเดสก์ท็อปคือการลากและวาง เมื่อวางไฟล์ .excalidraw
ลงในแอปพลิเคชันใน Excalidraw ไฟล์จะเปิดขึ้นทันทีและฉันก็เริ่มแก้ไขได้ ในเบราว์เซอร์ที่รองรับ File System Access API ก็สามารถบันทึกการเปลี่ยนแปลงได้ทันที คุณไม่จำเป็นต้องไปที่กล่องโต้ตอบการบันทึกไฟล์เนื่องจากได้รับแฮนเดิลไฟล์ที่จำเป็นจากการดำเนินการลากและวางแล้ว
เคล็ดลับที่จะทำให้สิ่งนี้เกิดขึ้นคือการเรียกใช้ getAsFileSystemHandle()
ในรายการการโอนข้อมูลเมื่อระบบรองรับ File System Access API แล้วส่งแฮนเดิลไฟล์นี้ให้ loadFromBlob()
ซึ่งคุณอาจจำได้จาก 2-3 ย่อหน้าด้านบน คุณสามารถทำสิ่งต่างๆ กับไฟล์ได้มากมาย เช่น การเปิด การบันทึก การบันทึกมากเกินไป การลาก การวาง เพื่อนร่วมงานผม Pete
และเราได้บันทึกกลเม็ดเคล็ดลับเหล่านี้ทั้งหมดและสิ่งอื่นๆ ไว้ในบทความของเรา เพื่อให้คุณ
สามารถติดตามผลได้เผื่อว่าทุกอย่างจะเร็วไปหน่อย
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 ฉันอยู่ในแอป Files ในโฟลเดอร์ Downloads
ดูไฟล์ได้ 2 ไฟล์ โดยไฟล์หนึ่งมีชื่อที่ไม่ใช่คำอธิบาย untitled
และมีการประทับเวลา ถ้าอยากดูข้อมูล
ให้คลิกจุด 3 จุด แล้วแชร์ จากนั้นตัวเลือกหนึ่งที่ปรากฏขึ้นคือ Excalidraw เมื่อแตะไอคอนดังกล่าว ก็จะเห็นว่าไฟล์มีแต่โลโก้ I/O อีกครั้ง
Lipis บนเวอร์ชันอิเล็กตรอนที่เลิกใช้งานแล้ว
สิ่งหนึ่งที่คุณทำได้กับไฟล์ที่ผมยังไม่ได้พูดถึงก็คือ doubleclick ไฟล์ สิ่งที่จะเกิดขึ้นเมื่อคุณ doubleclick ไฟล์ คือแอปที่เชื่อมโยงกับประเภท MIME ของไฟล์นั้นเปิดขึ้น ตัวอย่างเช่น สำหรับ .docx
จะเป็น Microsoft Word
Excalidraw เคยมีแอปเวอร์ชัน Electron ที่รองรับการเชื่อมโยงประเภทไฟล์ดังกล่าว ดังนั้นเมื่อคุณดับเบิลคลิกไฟล์ .excalidraw
แอป Excalidraw Electron จะเปิดขึ้น Lipis ที่คุณเคยพบก่อนหน้านี้เป็นผู้สร้างและเป็นผู้เลิกใช้งาน Excalidraw Electron เราถามเขาว่าทำไมถึงคิดว่าควรเลิกใช้งานเวอร์ชัน Electron
ผู้คนถามถึงแอป Electron มาตั้งแต่ต้น โดยมีเหตุผลหลักคือต้องการเปิดไฟล์ด้วยการดับเบิลคลิก และเราตั้งใจที่จะนำแอปนี้ไปใส่ไว้ใน App Store ด้วย ในขณะเดียวกัน มีคนแนะนำให้สร้าง PWA แทน เราจึงสร้างทั้ง 2 อย่าง โชคดีที่เราได้รู้จัก Project Fugu ซึ่งเป็น API ต่างๆ เช่น การเข้าถึงระบบไฟล์ การเข้าถึงคลิปบอร์ด การจัดการไฟล์ และอื่นๆ เพียงคลิกเดียว คุณก็สามารถติดตั้งแอปบนเดสก์ท็อปหรือในอุปกรณ์เคลื่อนที่ได้โดยไม่ต้องใช้อิเล็กตรอนให้หนักขึ้น การตัดสินใจง่ายๆ จะเลิกใช้งานเวอร์ชันอิเล็กตรอน มุ่งเน้นแค่เว็บแอป และทำให้เป็น PWA ที่เป็นไปได้มากที่สุด ยิ่งไปกว่านั้น ตอนนี้เราเผยแพร่ PWA ไปยัง Play Store และ Microsoft Store ได้แล้ว เยี่ยมไปเลย
อาจกล่าวได้ว่า Excalidraw สำหรับอิเล็กตรอนไม่ได้ถูกเลิกใช้งานเพราะอิเล็กตรอนนั้นแย่ ก็ไม่ดีเลย แต่เป็นเพราะเว็บมีคุณภาพดีพอ ฉันชอบ
การจัดการไฟล์
ที่ผมพูดว่า "เว็บมีคุณภาพดีพอแล้ว" ก็เพราะฟีเจอร์อย่างการจัดการไฟล์ที่กำลังจะมีขึ้น
นี่คือการติดตั้ง macOS Big Sur แบบปกติ ตอนนี้มาดูสิ่งที่จะเกิดขึ้นเมื่อฉันคลิกขวาที่ไฟล์ Excaliburaw ฉันเลือกเปิดด้วย Excalidraw ซึ่งเป็น PWA ที่ติดตั้งไว้ได้ แน่นอนว่าการดับเบิลคลิกก็ใช้ได้เช่นกัน แต่การสาธิตในหน้าจอแคสต์จะดูไม่น่าสนใจเท่า
แล้วฟีเจอร์นี้ทำงานอย่างไร ขั้นตอนแรกคือทำให้ระบบปฏิบัติการรู้จักประเภทไฟล์ที่แอปพลิเคชันของฉันจัดการได้ ฉันทำในช่องใหม่ชื่อ file_handlers
ในไฟล์ Manifest ของเว็บแอป ค่าของเมตริกคืออาร์เรย์ของออบเจ็กต์ที่มีการดำเนินการและพร็อพเพอร์ตี้ 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
นี้มีช่องที่เรียกว่า "File" ที่ทำให้ฉันมีแฮนเดิลไฟล์ที่หลากหลาย ฉันสนใจเฉพาะรายการแรกเท่านั้น และจากแฮนเดิลไฟล์นี้ เราได้รับ 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 Handling API ในบทความของฉัน คุณสามารถเปิดใช้การจัดการไฟล์ได้โดยตั้งค่าสถานะฟีเจอร์แพลตฟอร์มเว็บแบบทดลอง ซึ่งคาดว่าจะเปิดตัวใน Chrome ภายในปีนี้
การผสานรวมคลิปบอร์ด
ฟีเจอร์เจ๋งๆ อีกอย่างหนึ่งของ Excalidraw คือการผสานรวมคลิปบอร์ด ฉันสามารถคัดลอกภาพวาดทั้งภาพหรือแค่บางส่วนลงในคลิปบอร์ด อาจจะเพิ่มลายน้ำหากต้องการ แล้ววางลงในแอปอื่นได้ นี่เป็นแอป Paint เวอร์ชันเว็บของ Windows 95
วิธีการทำงานของฟีเจอร์นี้ง่ายเกินคาด สิ่งที่ฉันต้องการคือ Canvas เป็น BLOB แล้วเขียนลงในคลิปบอร์ดโดยการส่งอาร์เรย์ 1 เอลิเมนต์ที่มี ClipboardItem
ที่มี BLOB ไปยังฟังก์ชัน navigator.clipboard.write()
ดูข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่คุณทำได้ด้วย คลิปบอร์ด API ดูจาก Jason และบทความของฉัน
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 ของเซสชัน
คุณรู้ไหมว่า Excalidraw มีโหมดการทำงานร่วมกันด้วย แต่ละคนสามารถทำงานร่วมกัน ในเอกสารเดียวกัน ฉันคลิกปุ่มการทำงานร่วมกันแบบสด แล้วเริ่มเซสชันเพื่อเริ่มเซสชันใหม่ ฉันแชร์ URL ของเซสชันกับผู้ทำงานร่วมกันได้อย่างง่ายดายด้วย Web Share API ที่ Excalidraw ผสานรวมไว้
การทำงานร่วมกันแบบเรียลไทม์
เราได้จำลองเซสชันการทำงานร่วมกันในเครื่องโดยแก้ไขโลโก้ Google I/O ใน Pixelbook, โทรศัพท์ Pixel 3a และ iPad Pro คุณจะเห็นได้ว่าการเปลี่ยนแปลงที่เราทำในอุปกรณ์เครื่องหนึ่งจะแสดงในอุปกรณ์อื่นๆ ทั้งหมด
และเคอร์เซอร์ทั้งหมดเคลื่อนที่ไปมาได้ด้วย เคอร์เซอร์ของ Pixelbook ขยับอย่างต่อเนื่องเพราะควบคุมด้วยแทร็กแพด แต่เคอร์เซอร์ของโทรศัพท์ Pixel 3a และเคอร์เซอร์ในแท็บเล็ต iPad Pro ก็กระตุกไปมา เพราะฉันควบคุมอุปกรณ์เหล่านี้ด้วยการแตะด้วยนิ้วมือ
การดูสถานะของผู้ทำงานร่วมกัน
เพื่อปรับปรุงประสบการณ์การทำงานร่วมกันแบบเรียลไทม์ แม้กระทั่งระบบตรวจจับเมื่อไม่มีการใช้งาน เคอร์เซอร์ของ iPad Pro แสดงจุดสีเขียวเมื่อฉันใช้ จุดจะเปลี่ยนเป็นสีดำเมื่อฉันเปลี่ยนไปยังแท็บเบราว์เซอร์หรือแอปอื่น และเมื่อฉันอยู่ในแอป Excalidraw แต่ไม่ได้ทำอะไรเลย เคอร์เซอร์แสดงว่าฉันไม่มีการใช้งาน โดยมีสัญลักษณ์ zZZ ทั้ง 3 ตัว
นักอ่านสื่อเผยแพร่ของเราอาจมีแนวโน้มที่จะคิดว่าการตรวจจับเมื่อไม่มีการใช้งานผ่าน Idle Detection API ซึ่งเป็นข้อเสนอระยะแรกที่มีการดำเนินการในบริบทของ Project Fugu ระวังสปอยล์: ไม่ใช่นะ แม้ว่าเราจะติดตั้งโดยใช้ API นี้ใน Excalidraw แต่ท้ายที่สุดแล้ว เราตัดสินใจใช้แนวทางแบบดั้งเดิมที่อิงกับการวัดการเคลื่อนที่ของตัวชี้และระดับการเข้าถึงหน้าเว็บ
เราได้ส่งความคิดเห็นเกี่ยวกับสาเหตุที่ Idle Detection API ไม่สามารถแก้ปัญหา Use Case ที่เรามี Project Fugu API ทั้งหมดกำลังได้รับการพัฒนาแบบเปิดกว้าง เพื่อให้ทุกคนร่วมแสดงความคิดเห็นและรับฟังได้
Lipis กับสิ่งที่ขวางกั้นเอ็กซ์คาลิดรอว์
จากคำถามข้อสุดท้าย ผมได้ถาม lipis หนึ่งคำถามสุดท้าย เกี่ยวกับสิ่งที่เขาคิดว่าขาดไปจากแพลตฟอร์มเว็บ ที่ระงับ Excalidraw
File System Access API นั้นยอดเยี่ยม แต่คุณรู้ไหม ไฟล์ส่วนใหญ่ที่ฉันสนใจทุกวันนี้ อยู่ใน Dropbox หรือ Google ไดรฟ์ ไม่ได้อยู่ในฮาร์ดดิสก์ ฉันอยากให้ File System Access API ใส่เลเยอร์แอบสแตรกชันให้กับผู้ให้บริการระบบไฟล์ระยะไกลอย่าง Dropbox หรือ Google เพื่อผสานรวมและนักพัฒนาซอฟต์แวร์สามารถเขียนโค้ดได้ จากนั้นผู้ใช้ก็วางใจได้ว่าไฟล์จะปลอดภัยเมื่ออยู่กับผู้ให้บริการระบบคลาวด์ที่ตนเชื่อถือ
เราเห็นด้วยกับ lipis อย่างยิ่ง เราอยู่ในระบบคลาวด์ด้วย เราหวังว่าจะนำการเปลี่ยนแปลงนี้ไปใช้ได้ ในเร็วๆ นี้
โหมดแอปพลิเคชันแบบแท็บ
ว้าว เราได้เห็นการผสานรวม API ที่ยอดเยี่ยมมากมายใน Excalidraw ระบบไฟล์ การจัดการไฟล์ คลิปบอร์ด การแชร์เว็บ และ เป้าหมายการแชร์เว็บ แต่มีอีกเรื่องหนึ่ง ก่อนหน้านี้ผมสามารถแก้ไข เอกสารได้ทีละ 1 ฉบับเท่านั้น ไม่ได้แล้ว โปรดลองใช้โหมดแอปพลิเคชันแบบแท็บเวอร์ชันแรกใน Excalidraw ซึ่งมีลักษณะดังนี้
ฉันมีไฟล์ที่เปิดอยู่ใน Excalidraw PWA ที่ติดตั้งไว้ซึ่งทำงานในโหมดสแตนด์อโลน ตอนนี้ ผมจะเปิดแท็บใหม่ในหน้าต่างแบบสแตนด์อโลน แท็บนี้ไม่ใช่แท็บเบราว์เซอร์ปกติ แต่เป็นแท็บ PWA ในแท็บใหม่นี้ ฉันจะเปิดไฟล์รองและทำงานกับไฟล์เหล่านั้นได้อิสระจากหน้าต่างแอปเดียวกัน
โหมดแอปพลิเคชันแบบแท็บอยู่ในช่วงเริ่มต้นและไม่ได้มีทุกอย่างตายตัว หากสนใจ โปรดอ่านสถานะปัจจุบันของฟีเจอร์นี้ในบทความของฉัน
เปิดจากขอบ
หากต้องการติดตามข่าวสารเกี่ยวกับฟีเจอร์นี้และฟีเจอร์อื่นๆ โปรดดูเครื่องมือติดตาม Fugu API เรายินดีเป็นอย่างยิ่งที่จะผลักดันให้เว็บก้าวไปข้างหน้าและ ช่วยให้คุณทำสิ่งต่างๆ บนแพลตฟอร์มได้มากขึ้น ขอแนะนำ Excalidraw ที่ปรับปรุงใหม่ และนี่คือแอปพลิเคชัน เจ๋งๆ ทั้งหมดที่คุณสร้าง เริ่มสร้างได้ที่ excalidraw.com
เราหวังว่าจะเห็น API บางรายการที่เราได้แสดงในวันนี้ปรากฏในแอปของคุณ ผมชื่อต้อม จะหาผมเจอในฐานะ @tomayac ใน Twitter และในอินเทอร์เน็ต ขอขอบคุณอย่างยิ่งที่รับชมและสนุกกับ Google I/O