嘗試在網路上以擬物化方式,透過 Window Controls Overlay API 和 Ambient Light Sensor API 重新建立太陽計算機。
難題
我是 1980 年代的孩子,我讀高中時,太陽能計算機非常流行。學校為我們準備了 TI-30X SOLAR,我還記得當時大家會互相比較計算機的效能,方法是計算 69 的階乘,這是 TI-30X 能處理的最大數字。(速度差異非常明顯,我還是不知道為什麼)。
現在,將近 28 年後,我想以 HTML、CSS 和 JavaScript 重新建立計算機,作為有趣的 Designcember 挑戰。我不是設計師,因此並非從頭開始,而是使用 CodePen 的 Sassja Ceballos。
讓使用者可以安裝
雖然這是不錯的起點,但我決定要全力以赴,打造出最棒的擬物化設計。第一步是將其設為 PWA,以便安裝。
self.addEventListener('install', (event) => {
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
self.clients.claim();
event.waitUntil(
(async () => {
if ('navigationPreload' in self.registration) {
await self.registration.navigationPreload.enable();
}
})(),
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(
(async () => {
try {
const response = await event.preloadResponse;
if (response) {
return response;
}
return fetch(event.request);
} catch {
return new Response('Offline');
}
})(),
);
});
使用行動裝置混合
現在應用程式已可安裝,下一個步驟是盡可能與作業系統應用程式融為一體。在行動裝置上,我可以在 Web 應用程式資訊清單中將顯示模式設為 fullscreen
,藉此完成這項操作。
{
"display": "fullscreen"
}
在有相機孔或凹口的裝置上,調整檢視區塊,讓內容涵蓋整個螢幕,應用程式看起來就會很美觀。
<meta name="viewport" content="initial-scale=1, viewport-fit=cover" />
與桌面融合
在桌機上,我可以使用一項很酷的功能:視窗控制項重疊顯示,將內容放在應用程式視窗的標題列中。第一步是覆寫顯示模式備用序列,以便在可用時優先使用 window-controls-overlay
。
{
"display_override": ["window-controls-overlay"]
}
這樣一來,標題列就會消失,內容也會向上移至標題列區域,彷彿標題列不存在。我的想法是將擬物化太陽能電池移到標題列,並相應地將計算機 UI 的其餘部分向下移動,這可以使用一些使用 titlebar-area-*
環境變數的 CSS 來完成。你會發現所有選取器都帶有 wco
類別,這與下幾段內容有關。
#calc_solar_cell.wco {
position: fixed;
left: calc(0.25rem + env(titlebar-area-x, 0));
top: calc(0.75rem + env(titlebar-area-y, 0));
width: calc(env(titlebar-area-width, 100%) - 0.5rem);
height: calc(env(titlebar-area-height, 33px) - 0.5rem);
}
#calc_display_surface.wco {
margin-top: calc(env(titlebar-area-height, 33px) - 0.5rem);
}
接著,我需要決定要將哪些元素設為可拖曳,因為通常用於拖曳的標題列無法使用。我甚至可以套用 (-webkit-)app-region: drag
,讓整個計算機 (按鈕除外) 都能拖曳,按鈕則會取得 (-webkit-)app-region: no-drag
,因此無法用於拖曳。
#calc_inside.wco,
#calc_solar_cell.wco {
-webkit-app-region: drag;
app-region: drag;
}
button {
-webkit-app-region: no-drag;
app-region: no-drag;
}
最後一個步驟是讓應用程式對視窗控制項重疊顯示變更做出反應。在真正的漸進式強化方法中,我只會在瀏覽器支援這項功能時載入相關程式碼。
if ('windowControlsOverlay' in navigator) {
import('/wco.js');
}
每當視窗控制項重疊幾何圖形變更時,我都會修改應用程式,盡可能讓它看起來自然。建議您對這個事件進行去抖動處理,因為使用者調整視窗大小時,這個事件可能會頻繁觸發。也就是說,我會將 wco
類別套用至某些元素,因此上述 CSS 會生效,我也會變更主題顏色。我可以檢查 navigator.windowControlsOverlay.visible
屬性,偵測視窗控制項疊加層是否顯示。
const meta = document.querySelector('meta[name="theme-color"]');
const nodes = document.querySelectorAll(
'#calc_display_surface, #calc_solar_cell, #calc_outside, #calc_inside',
);
const toggleWCO = () => {
if (!navigator.windowControlsOverlay.visible) {
meta.content = '';
} else {
meta.content = '#385975';
}
nodes.forEach((node) => {
node.classList.toggle('wco', navigator.windowControlsOverlay.visible);
});
};
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
navigator.windowControlsOverlay.ongeometrychange = debounce((e) => {
toggleWCO();
}, 250);
toggleWCO();
現在一切就緒,我取得的計算機小工具幾乎就像經典的 Winamp,搭配其中一個舊式 Winamp 主題。現在我可以在桌面上隨意放置計算機,然後按一下右上角的尖角,啟用視窗控制功能。
實際運作的太陽能電池
為了展現極致的技術,我當然需要讓太陽能電池實際運作。只有在光線充足時,計算機才能正常運作。我透過 CSS 變數 --opacity
設定顯示器上數字的 CSS opacity
,並透過 JavaScript 控制該變數,藉此建立模型。
:root {
--opacity: 0.75;
}
#calc_expression,
#calc_result {
opacity: var(--opacity);
}
為偵測是否有足夠的光線供計算機運作,我使用 AmbientLightSensor
API。如要使用這個 API,我需要在 about:flags
中設定 #enable-generic-sensor-extra-classes
旗標,並要求 'ambient-light-sensor'
權限。和先前一樣,我使用漸進式強化功能,只在支援 API 時載入相關程式碼。
if ('AmbientLightSensor' in window) {
import('/als.js');
}
感應器會在有新讀數時,以勒克斯為單位傳回環境光。根據一般光線狀況的值表,我設計出非常簡單的公式,可將照度值轉換為介於 0 和 1 之間的值,並以程式輔助方式指派給 --opacity
變數。
const luxToOpacity = (lux) => {
if (lux > 250) {
return 1;
}
return lux / 250;
};
const sensor = new window.AmbientLightSensor();
sensor.onreading = () => {
console.log('Current light level:', sensor.illuminance);
document.documentElement.style.setProperty(
'--opacity',
luxToOpacity(sensor.illuminance),
);
};
sensor.onerror = (event) => {
console.log(event.error.name, event.error.message);
};
(async () => {
const {state} = await navigator.permissions.query({
name: 'ambient-light-sensor',
});
if (state === 'granted') {
sensor.start();
}
})();
在下方影片中,你可以看到我將室內燈光調亮到一定程度後,計算機開始運作。這樣就完成了!您現在擁有一個可實際運作的擬物化太陽能計算機。我那台老舊的 TI-30X SOLAR 計算機確實已陪伴我走過漫漫長路。
示範
請務必試用 Designcember 計算機範例,並查看 GitHub 上的原始碼。(如要安裝應用程式,請在獨立視窗中開啟應用程式。(下方的嵌入版本不會觸發迷你資訊列。)
Designcember 快樂!