網路功能
我們希望可以消除網路與原生之間的功能差距,並讓開發人員輕鬆打造開放網路的優質體驗。我們深信,每一位開發人員都應能存取必備的優質網頁體驗,我們也致力於打造功能更強大的網頁。
不過,部分功能可在原生環境中使用,但無法透過網路存取。也就是說,某些類型的應用程式無法在網路上提供,或較不實用。
我們會以開放且透明的方式設計及開發這些新功能,並使用現有的開放式網路平台標準程序,同時收集開發人員和其他瀏覽器廠商的早期意見回饋,以確保各項設計能反覆運作。
建構項目
在這個程式碼研究室中,您將使用全新網路 API,或僅可在標記後方使用網路 API。因此,此程式碼研究室將重點放在 API 本身,以及這些 API 解鎖的用途,而非建構特定最終產品。
您將會瞭解的內容
本程式碼研究室將教導幾種先進 API 的基本運作機制。請注意,這些機制目前還不可能成為石頭,非常感謝你對開發人員流程的意見。
軟硬體需求
本程式碼研究室中所列的 API 其實在最前一階段,因此每個 API 的相關規定都不太一樣。請務必仔細閱讀各部分開頭的相容性資訊。
如何執行程式碼研究室
程式碼研究室不一定是依序操作。每個部分都代表一個獨立的 API,因此您可以隨意挑選最感興趣的項目。
Badging API 的目標是讓使用者入手,並關注背景中發生的事情。為了簡化本程式碼研究室的示範流程,我們來使用 API 引導使用者探索前所未見的事物。這時您就可以暫時改用背景作業。
安裝 Airhorner
為了讓這個 API 正常運作,您需要安裝在桌面上的 PWA,因此第一步是安裝 PWA,例如著名的 airhorner.com。您可以點選右上角的 [安裝] 按鈕,或使用三點選單手動安裝。

這樣就會看到確認提示,請按一下 [安裝]。

現在您的作業系統中有一個新的圖示。按一下即可啟動 PWA。這類應用程式有專屬應用程式視窗,而且會以獨立模式執行。
|
|
設定徽章
已安裝 PWA 後,您需要取得一些數值資料 (徽章只能包含數字)。「空中大逃殺」是一件簡單的事,而「sigh」便是她的角子數量。事實上,透過已安裝的「Airhorner」應用程式,試著將馬角改動並檢查徽章。每當你發動

那麼,它是怎麼運作的?基本上,程式碼如下:
let hornCounter = 0;
const horn = document.querySelector('.horn');
horn.addEventListener('click', () => {
navigator.setExperimentalAppBadge(++hornCounter);
});
聽見汽車的聲音,然後查看 PWA 的圖示:這個圖示會更新一次。就是這麼簡單!

清除徽章
從 99 開始往前。您也可以手動重設。開啟「開發人員工具控制台」分頁,貼上下方的文字行,然後按 Enter 鍵。
navigator.setExperimentalAppBadge(0);
或者,您也可以清除徽章,如以下程式碼片段所示。PWA 的圖示現在看起來應該看起來像開頭、清晰且沒有徽章。
navigator.clearExperimentalAppBadge();

說明
您對這個 API 有何看法?請填寫這份簡短的問卷調查,協助我們解決您的問題:
這個 API 是否易於使用?
您有找到執行範例嗎?
還有其他想法嗎?有遺漏的功能嗎?請在這份問卷調查中提供快速的意見回饋。感謝您!
Native File System API 可讓開發人員建立強大的網路應用程式,在使用者裝置的裝置上與檔案互動。使用者授予網頁應用程式存取權後,這個 API 可讓網頁應用程式直接讀取或儲存使用者裝置上的檔案和資料夾。
讀取檔案
Native File System API 的「Hello, world」是用於讀取本機檔案並取得檔案內容。建立純文字 .txt 檔案並輸入一些文字。接下來,瀏覽至任何安全網站 (例如透過 HTTPS 提供服務的網站),例如 example.com 並開啟 DevTools 主控台。在主控台中貼上下方的程式碼片段。由於 Native File System API 需要使用者手勢,因此我們會在文件中附加 DoubleClick Search 處理常式。稍後我們將處理這個檔案處理,因此將其成為全域變數。
document.ondblclick = async () => {
window.handle = await window.chooseFileSystemEntries();
const file = await handle.getFile();
document.body.textContent = await file.text();
};

之後在 example.com 頁面的任意位置按兩下,系統就會顯示檔案選擇器。

選取您先前建立的 .txt 檔案。檔案內容會取代 example.com 的實際 body 內容。

儲存檔案
接下來,我們想做一些修改。因此,讓我們透過貼上下方程式碼片段的方式,修改 body。現在,您可以編輯文字,就像瀏覽器是文字編輯器一樣。
document.body.contentEditable = true;

現在,我們要將這些變更寫回原始檔案。因此,我們需要對檔案寫入者的寫入者,方法是在主控台中貼上下方的程式碼片段。再次需要用到使用者手勢,因此我們必須等候主要文件點擊。
document.onclick = async () => {
const writer = await handle.createWriter();
await writer.truncate(0);
await writer.write(0, document.body.textContent);
await writer.close();
};

現在按一下 (而非按兩下) 文件時,系統會顯示權限提示。授予權限後,檔案內容就會是您先前在「body」中編輯過的內容。請使用其他編輯器開啟變更檔案 (或是再次按兩下文件並重新開啟檔案,以再次進行驗證程序)。


恭喜!你剛剛建立了世界上最小的文字編輯器 [citation needed]。
說明
您對這個 API 有何看法?請填寫這份簡短的問卷調查,協助我們解決您的問題:
這個 API 是否易於使用?
您有找到執行範例嗎?
還有其他想法嗎?有遺漏的功能嗎?請在這份問卷調查中提供快速的意見回饋。感謝您!
Shape Detection API 可讓您存取加速圖形偵測器 (例如用於人臉),並處理靜態圖片和/或即時影像資訊提供。作業系統具備高效能且經過最佳化的功能偵測工具,例如 Android FaceDetector。Shape Detection API 會開啟這些原生實作,並透過一組 JavaScript 介面公開這些實作。
目前支援的功能是透過 FaceDetector 介面進行臉部偵測、透過 BarcodeDetector 介面偵測條碼,以及透過 TextDetector 介面偵測文字 (光學字元辨識)。
臉部偵測
Shape Detection API 的一項特色是臉部偵測。如要進行測試,請備妥含有臉孔的頁面。這個網頁包含作者的臉孔,是很好的開始。螢幕截圖看起來會像這樣。在支援的瀏覽器中,系統會識別臉孔的邊框和臉孔地標。
您可以重混或編輯 Glitch 專案 (尤其是 script.js 檔案),藉此瞭解必須花多少時間才能完成程式碼。

如要以動態方式呈現內容,而不只是搭配作者的臉孔使用,請前往這個 Google 搜尋結果網頁,透過私密分頁或訪客模式開啟完整臉孔功能。在該頁面中,於任何一處按一下滑鼠右鍵,然後點選 [檢查],開啟 Chrome 開發人員工具。接著,在 [主控台] 分頁中貼上下方的程式碼片段。這個程式碼會以半透明紅色方塊醒目顯示偵測到的臉孔。
document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
try {
const faces = await new FaceDetector().detect(img);
faces.forEach(face => {
const div = document.createElement('div');
const box = face.boundingBox;
const computedStyle = getComputedStyle(img);
const [top, right, bottom, left] = [
computedStyle.marginTop,
computedStyle.marginRight,
computedStyle.marginBottom,
computedStyle.marginLeft
].map(m => parseInt(m, 10));
const scaleX = img.width / img.naturalWidth;
const scaleY = img.height / img.naturalHeight;
div.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
div.style.position = 'absolute';
div.style.top = `${scaleY * box.top + top}px`;
div.style.left = `${scaleX * box.left + left}px`;
div.style.width = `${scaleX * box.width}px`;
div.style.height = `${scaleY * box.height}px`;
img.before(div);
});
} catch(e) {
console.error(e);
}
});
請注意,部分 DOMException 主題會自動處理,而且系統並未處理部分圖片。這是因為不需捲動位置的圖片會內嵌為資料 URI,因此可以存取,而「需捲動位置」圖片則是來自非支援 CORS 的不同網域。為方便示範,我們不必擔心。
臉部地標偵測
除了 SIM 卡之外,macOS 也支援偵測臉部地標的功能。如要測試臉部特徵的偵測效果,請將以下程式碼片段貼到主控台。提醒:由於 crbug.com/914348,地標的首選頻道根本不全然是完美的,但是你可以查看這個位置的標題和這項功能的強大效果。
document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
try {
const faces = await new FaceDetector().detect(img);
faces.forEach(face => {
const div = document.createElement('div');
const box = face.boundingBox;
const computedStyle = getComputedStyle(img);
const [top, right, bottom, left] = [
computedStyle.marginTop,
computedStyle.marginRight,
computedStyle.marginBottom,
computedStyle.marginLeft
].map(m => parseInt(m, 10));
const scaleX = img.width / img.naturalWidth;
const scaleY = img.height / img.naturalHeight;
div.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
div.style.position = 'absolute';
div.style.top = `${scaleY * box.top + top}px`;
div.style.left = `${scaleX * box.left + left}px`;
div.style.width = `${scaleX * box.width}px`;
div.style.height = `${scaleY * box.height}px`;
img.before(div);
const landmarkSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
landmarkSVG.style.position = 'absolute';
landmarkSVG.classList.add('landmarks');
landmarkSVG.setAttribute('viewBox', `0 0 ${img.width} ${img.height}`);
landmarkSVG.style.width = `${img.width}px`;
landmarkSVG.style.height = `${img.height}px`;
face.landmarks.map((landmark) => {
landmarkSVG.innerHTML += `<polygon class="landmark-${landmark.type}" points="${
landmark.locations.map((point) => {
return `${scaleX * point.x},${scaleY * point.y} `;
}).join(' ')
}" /></svg>`;
});
div.before(landmarkSVG);
});
} catch(e) {
console.error(e);
}
});
條碼偵測
形狀偵測 API 的第二個功能是條碼偵測。和先前一樣,我們需要一個含有條碼的網頁,例如這個。在瀏覽器中開啟檔案時,您會看到經過多次破解的 QR 圖碼。重新編輯或編輯 Glitch 專案,尤其是 script.js 檔案,瞭解其效果。

如果需要更多動態,我們可以再次使用「Google 圖片搜尋」。此時,請使用瀏覽器前往私密分頁或訪客模式中的這個 Google 搜尋結果網頁。現在,請將下方程式碼片段貼到 Chrome 開發人員工具控制台分頁中。不久之後,系統辨識出的條碼會以原始值和條碼類型加上註解。
document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
try {
const barcodes = await new BarcodeDetector().detect(img);
barcodes.forEach(barcode => {
const div = document.createElement('div');
const box = barcode.boundingBox;
const computedStyle = getComputedStyle(img);
const [top, right, bottom, left] = [
computedStyle.marginTop,
computedStyle.marginRight,
computedStyle.marginBottom,
computedStyle.marginLeft
].map(m => parseInt(m, 10));
const scaleX = img.width / img.naturalWidth;
const scaleY = img.height / img.naturalHeight;
div.style.backgroundColor = 'rgba(255, 255, 255, 0.75)';
div.style.position = 'absolute';
div.style.top = `${scaleY * box.top + top}px`;
div.style.left = `${scaleX * box.left - left}px`;
div.style.width = `${scaleX * box.width}px`;
div.style.height = `${scaleY * box.height}px`;
div.style.color = 'black';
div.style.fontSize = '14px';
div.textContent = `${barcode.rawValue}`;
img.before(div);
});
} catch(e) {
console.error(e);
}
});
文字偵測
圖形偵測 API 的最後一個功能是文字偵測。現在您知道該練習了:我們需要一個包含文字的圖片,像是包含「Google 圖書」掃描結果的這個網頁。在支援的瀏覽器中,你會看到文字已辨識,且文字段落周圍有定界框。重新編輯或編輯 Glitch 專案,尤其是 script.js 檔案,瞭解其效果。

如要以動態方式進行測試,請在私密分頁或訪客模式中前往這個搜尋結果網頁。現在,請將下方程式碼片段貼到 Chrome 開發人員工具控制台分頁中。只要稍候片刻,系統就會辨識部分文字。
document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
try {
const texts = await new TextDetector().detect(img);
texts.forEach(text => {
const div = document.createElement('div');
const box = text.boundingBox;
const computedStyle = getComputedStyle(img);
const [top, right, bottom, left] = [
computedStyle.marginTop,
computedStyle.marginRight,
computedStyle.marginBottom,
computedStyle.marginLeft
].map(m => parseInt(m, 10));
const scaleX = img.width / img.naturalWidth;
const scaleY = img.height / img.naturalHeight;
div.style.backgroundColor = 'rgba(255, 255, 255, 0.75)';
div.style.position = 'absolute';
div.style.top = `${scaleY * box.top + top}px`;
div.style.left = `${scaleX * box.left - left}px`;
div.style.width = `${scaleX * box.width}px`;
div.style.height = `${scaleY * box.height}px`;
div.style.color = 'black';
div.style.fontSize = '14px';
div.innerHTML = text.rawValue;
img.before(div);
});
} catch(e) {
console.error(e);
}
});
說明
您對這個 API 有何看法?請填寫這份簡短的問卷調查,協助我們解決您的問題:
這個 API 是否易於使用?
您有找到執行範例嗎?
還有其他想法嗎?有遺漏的功能嗎?請在這份問卷調查中提供快速的意見回饋。感謝您!
Web Share Target API 可讓安裝的網路應用程式向基礎作業系統註冊為共用目標,以接收來自 Web Share API 或系統事件 (例如作業系統層級分享按鈕) 的共用內容。
安裝要用來分享內容的 PWA
第一步是準備要分享的 PWA。目前,Airhorner (幸運的是) 無法執行工作,不過Web Share Target 試用版應用程式卻能滿足您的需求。將應用程式安裝到裝置的主畫面。

在 PWA 中分享內容
接下來,您必須提供要分享的內容,例如 Google 相簿中的相片。使用 [分享] 按鈕並選取 [貼圖簿 PWA] 做為共用目標。

輕觸「應用程式」圖示後,系統就會將您直接帶往 Scrapbook PWA,相片也會直接顯示在這裡。

那麼,它是怎麼運作的?如要瞭解詳情,請參閱 Scrapbook PWA 的網頁應用程式資訊清單。讓 Web Share Target API 運作的設定位於資訊清單的 "share_target" 屬性中,指出在 "action" 欄位中,其網址指向的是依照 "params" 中列出的參數。
然後,共用端就會據此填入這個網址範本 (透過共用動作執行,或是由開發人員使用 Web Share API 以程式輔助方式控管),以便接收端擷取參數並對其執行相關動作,例如顯示參數。
{
"action": "/_share-target",
"enctype": "multipart/form-data",
"method": "POST",
"params": {
"files": [{
"name": "media",
"accept": ["audio/*", "image/*", "video/*"]
}]
}
}
說明
您對這個 API 有何看法?請填寫這份簡短的問卷調查,協助我們解決您的問題:
這個 API 是否易於使用?
您有找到執行範例嗎?
還有其他想法嗎?有遺漏的功能嗎?請在這份問卷調查中提供快速的意見回饋。感謝您!
為避免耗電,多數裝置會在閒置時快速進入休眠狀態。雖然這在大部分時間都沒問題,但有些應用程式需要保持螢幕或裝置喚醒狀態,才能完成工作。Wake Lock API 可以防止裝置調暗及鎖定螢幕,或禁止裝置進入休眠狀態。這項功能讓新體驗需要原生應用程式才能使用。
設定螢幕保護程式
如要測試 Wake Lock API,您必須先確認裝置「確實」進入休眠狀態。因此,在您的作業系統偏好設定窗格中啟用您選擇的螢幕保護程式,並確認在 1 分鐘後啟動。請確定裝置本身是在您指定的時間繼續運作 (是,我知道這很麻煩),下方的螢幕截圖顯示 macOS,不過您可以在自己的 Android 裝置或任何相關的電腦版平台上試用這項功能。

設定螢幕 Wake Lock
確定您的螢幕保護程式運作正常後,您將會使用 "screen" 類型的 Wake Lock 來防止螢幕保護程式執行工作。前往 Wake Lock 示範應用程式,然後依序點選 [啟用] screen [Wake Lock] 核取方塊。

即日起,系統會啟用 Wake Lock。如果您有足夠的病患離開裝置,裝置很快就會保持閒置狀態,您會看到螢幕保護程式已經開始啟動了。
這是什麼功能呢?如要瞭解詳情,請前往 Wake Lock 示範應用程式的 Glitch 專案,並查看 script.js。程式碼的重心放在下方的程式碼片段中。開啟新分頁 (或使用任何已開啟的分頁),並將下列程式碼貼到 Chrome 開發人員工具主控台中。然後,您將在窗口中看到一個 10 秒激活的 Wake Lock 檢查一個 10 秒(查看控制台日誌),您的屏幕銳步器都不起時起。
if ('wakeLock' in navigator && 'request' in navigator.wakeLock) {
let wakeLock = null;
const requestWakeLock = async () => {
try {
wakeLock = await navigator.wakeLock.request('screen');
wakeLock.addEventListener('release', () => {
console.log('Wake Lock was released');
});
console.log('Wake Lock is active');
} catch (e) {
console.error(`${e.name}, ${e.message}`);
}
};
requestWakeLock();
window.setTimeout(() => {
wakeLock.release();
}, 10 * 1000);
}

說明
您對這個 API 有何看法?請填寫這份簡短的問卷調查,協助我們解決您的問題:
這個 API 是否易於使用?
您有找到執行範例嗎?
還有其他想法嗎?有遺漏的功能嗎?請在這份問卷調查中提供快速的意見回饋。感謝您!
我們非常期待使用的 API 就是 Contact Picker API。這會允許網頁應用程式存取裝置內建的聯絡人管理工具,以便您的網路應用程式存取聯絡人的名稱、電子郵件地址和電話號碼。您可選擇只指定一位或多位聯絡人,並指明要輸入所有欄位,還是只輸入部分名稱、電子郵件地址和電話號碼。
隱私權考量
挑選器開啟後,您就可以選取要共用的聯絡人。您會注意到,您無法選取 [全選] 選項,因為這項做法的用意在於謹慎地分享。同樣地,存取權並非持續,而是一次性的決定。
存取聯絡人
存取聯絡人是一件簡單的工作,在挑選器開啟之前,您可以指定所需的欄位 (選項包括 name、email 和 telephone),以及要存取多個聯絡人,還是只存取單一聯絡人。您可以在 Android 裝置上開啟試用版應用程式,測試這個 API。原始碼的相關部分,基本上是下方的程式碼片段:
getContactsButton.addEventListener('click', async () => {
const contacts = await navigator.contacts.select(
['name', 'email'],
{multiple: true});
if (!contacts.length) {
// No contacts were selected, or picker couldn't be opened.
return;
}
console.log(contacts);
});

複製及貼上文字
目前,您無法以程式輔助的方式將圖片複製至系統的剪貼簿。我們最近在 Async Clipboard API 新增了圖片支援功能,
這樣就能在周圍複製和貼上圖片更棒的是,您也可以將圖片寫入剪貼簿。非同步剪貼簿 API 支援在一段時間內複製及貼上文字。呼叫 Navgator.clipboard.writeText() 之後,就可以透過呼叫 Navgator.clipboard.readText() 將文字複製到剪貼簿。
複製及貼上圖片
現在您也可以將圖片寫入剪貼簿。為此,您需要以圖片形式將圖片資料插入 Blob 資料,再將其傳送至剪貼簿項目建構函式。最後,您可以呼叫 Navgator.clipboard.write(),藉此複製這個剪貼簿項目。
// Copy: Writing image to the clipboard
try {
const imgURL = 'https://developers.google.com/web/updates/images/generic/file.png';
const data = await fetch(imgURL);
const blob = await data.blob();
await navigator.clipboard.write([
new ClipboardItem(Object.defineProperty({}, blob.type, {
value: blob,
enumerable: true
}))
]);
console.log('Image copied.');
} catch(e) {
console.error(e, e.message);
}
將圖片從剪貼簿貼上圖片似乎相當複雜,但實際上只是將 Blob 從剪貼簿項目中還原。由於可能存在多個問題,您必須逐一瀏覽各個項目,直到有所需的項目為止。基於安全性考量,現在只能查看 PNG 圖片,但日後可能會支援更多圖片格式。
async function getClipboardContents() {
try {
const clipboardItems = await navigator.clipboard.read();
for (const clipboardItem of clipboardItems) {
try {
for (const type of clipboardItem.types) {
const blob = await clipboardItem.getType(type);
console.log(URL.createObjectURL(blob));
}
} catch (e) {
console.error(e, e.message);
}
}
} catch (e) {
console.error(e, e.message);
}
}
您可以在試用版應用程式中查看這個 API 的實際運作情形,此 API 的程式碼片段已嵌入在其原始碼中。您無須授予相關權限,就能將圖片複製到剪貼簿。不過,您必須授予將圖片從剪貼簿貼上的權限。

授予存取權後,您就可以從剪貼簿讀取圖片並將其貼到應用程式中:

恭喜!您完成了程式碼研究室的結尾。再次提醒您,多數 API 仍在處理中,而且仍在積極處理中。因此,我們十分重視您的意見回饋,因為只有與您「您」等使用者的互動才能幫助他們取得這些 API。
我們也建議您經常查看功能到達網頁。我們將持續更新這個類別,並針對我們所處理的 API 提供所有深入說明文章。繼續加油!
Tom 和整個功能團隊 🐡?
