ความพยายามเชิงคาดการณ์ในการสร้างเครื่องคำนวณพลังงานแสงอาทิตย์บนเว็บอีกครั้งโดยใช้ Window Controls Overlay API และ API เซ็นเซอร์แสงแวดล้อม
ความท้าทาย
ฉันเป็นเด็กยุค 1980 สิ่งที่เคยโกรธแค้นมากตอนที่เรียนอยู่ชั้นมัธยมปลาย คือเครื่องคำนวณพลังงานแสงอาทิตย์ เราทุกคนได้รับ TI-30X SOLAR จากโรงเรียน และฉันก็ชอบเปรียบเทียบเครื่องคำนวณของเราด้วยกันโดยการคำนวณแฟกทอเรียลของ 69 ซึ่งเป็นจำนวนสูงสุดที่ TI-30X สามารถทำได้ (ความแปรปรวนของความเร็วนั้นวัดได้มาก แต่ก็ยังไม่ทราบสาเหตุ)
ตอนนี้เป็นเวลาเกือบ 28 ปีแล้ว ผมคิดว่าคงเป็นเรื่องสนุกของ Designcember ที่จะสร้างเครื่องคิดเลขขึ้นใหม่ใน HTML, CSS และ JavaScript การไม่ได้เป็นนักออกแบบมากนัก ผมไม่ได้เริ่มใหม่ตั้งแต่ต้น แต่ร่วมด้วย CodePen โดย Sassja Ceballos
ทำให้ติดตั้งได้
แม้จะยังไม่ใช่จุดเริ่มต้นที่แย่ แต่ฉันตัดสินใจเร่งเครื่องเพื่อเติมความเจ๋งเต็มขั้น ขั้นตอนแรกคือ ทำให้เป็น PWA เพื่อให้สามารถติดตั้งได้ ฉันยังคงใช้เทมเพลต PWA พื้นฐานใน Glitch เพื่อนำไปรีมิกซ์เมื่อต้องการตัวอย่างสั้นๆ โปรแกรมทำงานของบริการจะไม่ชนะรางวัลการเขียนโค้ดให้คุณและยังไม่พร้อมใช้งานในเวอร์ชันที่ใช้งานจริง แต่เพียงพอที่จะทริกเกอร์แถบข้อมูลขนาดเล็กของ 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"]
}
ซึ่งทำให้แถบชื่อหายไปอย่างมีประสิทธิภาพ และเนื้อหาจะเลื่อนขึ้นไปหาในพื้นที่แถบชื่อราวกับว่าไม่มีแถบชื่ออยู่ แนวคิดของผมคือย้ายเซลล์แสงอาทิตย์แบบ Skeuomorphic ขึ้นไปในแถบชื่อและ UI ของเครื่องคำนวณส่วนที่เหลือลงมาตามความเหมาะสม ซึ่งผมสามารถทำได้กับ CSS บางรายที่ใช้ตัวแปรสภาพแวดล้อม titlebar-area-*
คุณจะเห็นว่าตัวเลือกทั้งหมดมีคลาส wco
ซึ่งจะเกี่ยวข้อง 2-3 ย่อหน้า
#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 เพื่อตรวจหาว่ามีแสงสว่างเพียงพอให้เครื่องคำนวณทำงานได้หรือไม่ เราต้องตั้งค่าแฟล็ก #enable-generic-sensor-extra-classes
ใน about:flags
และขอสิทธิ์ 'ambient-light-sensor'
เพื่อให้ API นี้ใช้งานได้ เหมือนก่อนหน้านี้ ผมใช้การเพิ่มประสิทธิภาพแบบต่อเนื่อง
เพื่อโหลดโค้ดที่เกี่ยวข้องเฉพาะเมื่อรองรับ 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();
}
})();
ในวิดีโอด้านล่าง คุณจะเห็นวิธีที่เครื่องคิดเลขเริ่มทำงานเมื่อผมเปิดไฟห้องเพียงพอ เท่านี้ก็เรียบร้อย เครื่องคำนวณพลังงานแสงอาทิตย์แบบ Skeuomorphic ใช้งานได้จริง TI-30X SOLAR ที่เคยมีมายาวนานมากของฉัน
ข้อมูลประชากร
อย่าลืมทดลองใช้เดโมเครื่องคิดเลข Designcember Calculator และดูซอร์สโค้ดใน Glitch (หากต้องการติดตั้งแอป คุณต้องเปิดแอปในหน้าต่างของแอปนั้นๆ เวอร์ชันที่ฝังด้านล่างนี้จะไม่เรียกใช้ แถบข้อมูลขนาดเล็ก)
ขอให้มีความสุขกับ Designcember