Một nỗ lực tạo hình skeuomorphic để tạo lại máy tính năng lượng mặt trời trên web bằng API Lớp phủ điều khiển cửa sổ và API cảm biến ánh sáng xung quanh.
Thách thức
Tôi là một đứa trẻ của thập niên 1980. Một thứ rất thịnh hành khi tôi còn học trung học là máy tính chạy bằng năng lượng mặt trời. Trường đã tặng cho chúng tôi một chiếc máy tính TI-30X SOLAR. Tôi vẫn nhớ như in những kỷ niệm chúng tôi so sánh hiệu suất của các máy tính với nhau bằng cách tính toán số mũ của 69, con số cao nhất mà TI-30X có thể xử lý. (Sự biến thiên về tốc độ rất dễ đo lường, tôi vẫn không biết lý do tại sao.)
Giờ đây, sau gần 28 năm, tôi nghĩ rằng việc tạo lại máy tính trong HTML, CSS và JavaScript sẽ là một thử thách thú vị trong Designcember. Không phải là một nhà thiết kế, tôi không bắt đầu từ đầu, mà bắt đầu bằng một CodePen của Sassja Ceballos.
Cho phép cài đặt
Mặc dù không phải là một khởi đầu tệ, nhưng tôi quyết định tăng cường để có được giao diện tuyệt vời đầy đủ. Bước đầu tiên là tạo một PWA để có thể cài đặt. Tôi duy trì một mẫu PWA cơ sở trên Glitch mà tôi phối lại bất cứ khi nào cần một bản minh hoạ nhanh. Worker dịch vụ của ứng dụng này sẽ không giúp bạn giành được giải thưởng lập trình nào và chắc chắn chưa sẵn sàng phát hành công khai, nhưng nó đủ để kích hoạt thanh thông tin mini của Chromium để có thể cài đặt ứng dụng.
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');
}
})(),
);
});
Kết hợp với thiết bị di động
Giờ đây, bạn có thể cài đặt ứng dụng. Bước tiếp theo là làm cho ứng dụng này hòa hợp với các ứng dụng hệ điều hành nhiều nhất có thể. Trên thiết bị di động, tôi có thể thực hiện việc này bằng cách đặt chế độ hiển thị thành fullscreen
trong Tệp kê khai ứng dụng web.
{
"display": "fullscreen"
}
Trên các thiết bị có lỗ máy ảnh hoặc phần cắt, việc điều chỉnh khung nhìn để nội dung bao phủ toàn bộ màn hình sẽ giúp ứng dụng trông bắt mắt.
<meta name="viewport" content="initial-scale=1, viewport-fit=cover" />
Kết hợp với máy tính
Trên máy tính, tôi có thể sử dụng một tính năng thú vị: Lớp phủ điều khiển cửa sổ. Tính năng này cho phép tôi đặt nội dung vào thanh tiêu đề của cửa sổ ứng dụng. Bước đầu tiên là ghi đè trình tự dự phòng của chế độ hiển thị để trước tiên, trình tự này sẽ cố gắng sử dụng window-controls-overlay
khi có.
{
"display_override": ["window-controls-overlay"]
}
Điều này giúp thanh tiêu đề biến mất một cách hiệu quả và nội dung di chuyển lên khu vực thanh tiêu đề như thể thanh tiêu đề không có ở đó. Ý tưởng của tôi là di chuyển pin mặt trời skeuomorphic lên thanh tiêu đề và phần còn lại của giao diện người dùng máy tính xuống tương ứng. Tôi có thể thực hiện việc này bằng một số CSS sử dụng biến môi trường titlebar-area-*
. Bạn sẽ thấy tất cả bộ chọn đều mang một lớp wco
. Lớp này sẽ có liên quan trong một vài đoạn bên dưới.
#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);
}
Tiếp theo, tôi cần quyết định phần tử nào có thể kéo được, vì thanh tiêu đề mà tôi thường sử dụng để kéo không có sẵn. Theo kiểu tiện ích cổ điển, tôi thậm chí có thể làm cho toàn bộ máy tính có thể kéo được bằng cách áp dụng (-webkit-)app-region: drag
, ngoài các nút nhận (-webkit-)app-region: no-drag
để không thể dùng để kéo.
#calc_inside.wco,
#calc_solar_cell.wco {
-webkit-app-region: drag;
app-region: drag;
}
button {
-webkit-app-region: no-drag;
app-region: no-drag;
}
Bước cuối cùng là làm cho ứng dụng phản ứng với các thay đổi của lớp phủ điều khiển cửa sổ. Trong phương pháp cải tiến tiến bộ thực sự, tôi chỉ tải mã cho tính năng này khi trình duyệt hỗ trợ tính năng này.
if ('windowControlsOverlay' in navigator) {
import('/wco.js');
}
Bất cứ khi nào các chế độ điều khiển cửa sổ thay đổi hình học lớp phủ, tôi sẽ sửa đổi ứng dụng để làm cho ứng dụng trông tự nhiên nhất có thể. Bạn nên loại bỏ độ trễ của sự kiện này vì sự kiện này có thể được kích hoạt thường xuyên khi người dùng đổi kích thước cửa sổ. Cụ thể, tôi áp dụng lớp wco
cho một số phần tử, vì vậy CSS từ trên sẽ kích hoạt và tôi cũng thay đổi màu giao diện. Tôi có thể phát hiện xem lớp phủ điều khiển cửa sổ có hiển thị hay không bằng cách kiểm tra thuộc tính 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();
Giờ đây, với tất cả những điều này, tôi có một tiện ích máy tính gần giống như Winamp cổ điển với một trong các giao diện Winamp kiểu cũ. Giờ đây, tôi có thể tự do đặt máy tính trên màn hình và kích hoạt tính năng điều khiển cửa sổ bằng cách nhấp vào biểu tượng mũi tên kép ở góc trên bên phải.
Một pin mặt trời đang hoạt động
Để có được sự đam mê công nghệ cao nhất, tất nhiên tôi cần phải làm cho pin mặt trời thực sự hoạt động. Máy tính chỉ hoạt động nếu có đủ ánh sáng. Cách tôi lập mô hình này là thông qua việc đặt CSS opacity
của các chữ số trên màn hình thông qua biến CSS --opacity
mà tôi kiểm soát thông qua JavaScript.
:root {
--opacity: 0.75;
}
#calc_expression,
#calc_result {
opacity: var(--opacity);
}
Để phát hiện xem có đủ ánh sáng để máy tính hoạt động hay không, tôi sử dụng API AmbientLightSensor
. Để sử dụng API này, tôi cần đặt cờ #enable-generic-sensor-extra-classes
trong about:flags
và yêu cầu quyền 'ambient-light-sensor'
. Như trước đây, tôi sử dụng tính năng cải tiến tiến bộ để chỉ tải mã liên quan khi API được hỗ trợ.
if ('AmbientLightSensor' in window) {
import('/als.js');
}
Cảm biến trả về ánh sáng xung quanh theo đơn vị lux mỗi khi có kết quả đo mới. Dựa trên bảng giá trị của các tình huống ánh sáng thông thường, tôi đã tạo ra một công thức rất đơn giản để chuyển đổi giá trị lux thành một giá trị từ 0 đến 1 mà tôi chỉ định theo phương thức cho biến --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();
}
})();
Trong video dưới đây, bạn có thể thấy cách máy tính bắt đầu hoạt động sau khi tôi bật đủ ánh sáng trong phòng. Và bạn đã có một máy tính năng lượng mặt trời mang tính mô phỏng thực sự hoạt động. Chiếc TI-30X SOLAR cũ đã được kiểm thử theo thời gian của tôi đã đi được một chặng đường dài.
Bản minh hoạ
Hãy nhớ chơi với bản minh hoạ Máy tính Designcember và xem mã nguồn trên Glitch. (Để cài đặt ứng dụng, bạn cần mở ứng dụng trong cửa sổ riêng. Phiên bản nhúng bên dưới sẽ không kích hoạt thanh thông tin mini.)
Chúc bạn có một Tháng 12 thiết kế vui vẻ!