การพยายามสร้างเครื่องคำนวณพลังงานแสงอาทิตย์ขึ้นมาใหม่บนเว็บด้วย Window Controls Overlay API และ Ambient Light Sensor API
ความท้าทาย
ฉันเป็นเด็กยุค 80 สิ่งที่ฮิตมากเมื่อตอนฉันเรียนมัธยมคือเครื่องคิดเลขพลังงานแสงอาทิตย์ โรงเรียนมอบTI-30X SOLAR ให้เราทุกคน และเรามีความทรงจำดีๆ เกี่ยวกับการเปรียบเทียบประสิทธิภาพเครื่องคิดเลขกันด้วยการคำนวณ factorial ของ 69 ซึ่งเป็นตัวเลขสูงสุดที่ TI-30X ทำได้ (ความแปรปรวนของความเร็ววัดได้ดีมาก แต่เรายังไม่ทราบสาเหตุ)
ตอนนี้เกือบ 28 ปีผ่านไปแล้ว เราคิดว่าการทําเครื่องคิดเลขใน HTML, CSS และ JavaScript อีกครั้งน่าจะเป็นงานที่สนุกสนานสำหรับ Designcember ในฐานะที่ไม่ใช่นักออกแบบ ฉันไม่ได้เริ่มต้นจากศูนย์ แต่ใช้ CodePen ของ Sassja Ceballos
ทำให้ติดตั้งได้
แม้ว่าการเริ่มต้นนี้จะไม่เลวร้าย แต่เราตัดสินใจที่จะเพิ่มประสิทธิภาพให้ยอดเยี่ยมยิ่งขึ้นด้วยการออกแบบที่เลียนแบบจริง ขั้นตอนแรกคือทำให้เป็น PWA เพื่อให้ติดตั้งได้ ฉันดูแลเทมเพลต PWA พื้นฐานใน Glitch ซึ่งจะรีมิกซ์ทุกครั้งที่ต้องการการสาธิตอย่างรวดเร็ว Service Worker ของบริการนี้จะไม่ทำให้คุณได้รับรางวัลการเขียนโค้ดใดๆ และยังไม่พร้อมใช้งานจริง แต่เพียงพอที่จะทริกเกอร์แถบข้อมูลขนาดเล็กของ Chromium เพื่อให้ติดตั้งแอปได้
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');
}
})(),
);
});
การผสานรวมกับอุปกรณ์เคลื่อนที่
เมื่อติดตั้งแอปได้แล้ว ขั้นตอนถัดไปคือทำให้แอปกลมกลืนกับแอประบบปฏิบัติการมากที่สุด บนอุปกรณ์เคลื่อนที่ ฉันจะทำได้โดยการตั้งค่าโหมดการแสดงผลเป็น fullscreen
ในไฟล์ Manifest ของเว็บแอป
{
"display": "fullscreen"
}
ในอุปกรณ์ที่มีรูกล้องหรือรอยบาก การปรับวิวพอร์ตเพื่อให้เนื้อหาครอบคลุมทั้งหน้าจอจะทำให้แอปดูสวยงาม
<meta name="viewport" content="initial-scale=1, viewport-fit=cover" />
การผสานรวมกับเดสก์ท็อป
ในเดสก์ท็อปมีฟีเจอร์เจ๋งๆ ที่ฉันใช้ได้ ซึ่งก็คือการวางซ้อนการควบคุมหน้าต่าง ซึ่งช่วยให้ฉันใส่เนื้อหาในแถบชื่อของหน้าต่างแอปได้ ขั้นตอนแรกคือการลบล้างลําดับการแสดงผลสำรองเพื่อให้ระบบพยายามใช้ window-controls-overlay
ก่อนหากมี
{
"display_override": ["window-controls-overlay"]
}
ซึ่งจะทำให้แถบชื่อหายไปอย่างมีประสิทธิภาพและเนื้อหาจะเลื่อนขึ้นไปในพื้นที่แถบชื่อราวกับว่าแถบชื่อนั้นไม่มีอยู่ แนวคิดของฉันคือการย้ายเซลล์แสงอาทิตย์แบบจำลองขึ้นมาที่แถบชื่อ และ UI ของส่วนที่เหลือของโปรแกรมคํานวณลงตามลำดับ ซึ่งฉันทําได้โดยใช้ CSS บางรายการที่ใช้ตัวแปรสภาพแวดล้อม titlebar-area-*
คุณจะเห็นว่าตัวเลือกทั้งหมดมีคลาส 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 นี้พร้อมใช้งาน เราต้องตั้งค่า Flag #enable-generic-sensor-extra-classes
ใน about:flags
และขอสิทธิ์ '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 และดูซอร์สโค้ดใน Glitch (หากต้องการติดตั้งแอป คุณต้องเปิดแอปในหน้าต่างของตัวเอง เวอร์ชันที่ฝังไว้ด้านล่างจะไม่ทริกเกอร์แถบข้อมูลขนาดเล็ก)
สุขสันต์Designcember