เครื่องคิดเลข Designcember Calculator

ความพยายามเชิงคาดการณ์ในการสร้างเครื่องคำนวณพลังงานแสงอาทิตย์บนเว็บอีกครั้งโดยใช้ Window Controls Overlay API และ API เซ็นเซอร์แสงแวดล้อม

ความท้าทาย

ฉันเป็นเด็กยุค 1980 สิ่งที่เคยโกรธแค้นมากตอนที่เรียนอยู่ชั้นมัธยมปลาย คือเครื่องคำนวณพลังงานแสงอาทิตย์ เราทุกคนได้รับ TI-30X SOLAR จากโรงเรียน และฉันก็ชอบเปรียบเทียบเครื่องคำนวณของเราด้วยกันโดยการคำนวณแฟกทอเรียลของ 69 ซึ่งเป็นจำนวนสูงสุดที่ TI-30X สามารถทำได้ (ความแปรปรวนของความเร็วนั้นวัดได้มาก แต่ก็ยังไม่ทราบสาเหตุ)

ตอนนี้เป็นเวลาเกือบ 28 ปีแล้ว ผมคิดว่าคงเป็นเรื่องสนุกของ Designcember ที่จะสร้างเครื่องคิดเลขขึ้นใหม่ใน HTML, CSS และ JavaScript การไม่ได้เป็นนักออกแบบมากนัก ผมไม่ได้เริ่มใหม่ตั้งแต่ต้น แต่ร่วมด้วย CodePen โดย Sassja Ceballos

มุมมอง CodePen ที่มีแผง HTML, CSS และ JS แบบซ้อนทางด้านซ้ายและตัวอย่างเครื่องคิดเลขทางด้านขวา

ทำให้ติดตั้งได้

แม้จะยังไม่ใช่จุดเริ่มต้นที่แย่ แต่ฉันตัดสินใจเร่งเครื่องเพื่อเติมความเจ๋งเต็มขั้น ขั้นตอนแรกคือ ทำให้เป็น 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" />

Designcember Calculator แสดงแบบเต็มหน้าจอในโทรศัพท์ Pixel 6 Pro

กลมกลืนไปกับเดสก์ท็อป

บนเดสก์ท็อป มีฟีเจอร์เจ๋งๆ ที่ผมใช้ได้คือ การวางซ้อนการควบคุมหน้าต่าง ซึ่งช่วยให้ฉันวางเนื้อหาลงในแถบชื่อของหน้าต่างแอปได้ ขั้นตอนแรกคือลบล้างลำดับสำรองของโหมดการแสดงผลเพื่อให้พยายามใช้ 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 แบบเดิม ตอนนี้ผมสามารถ วางเครื่องคิดเลขไว้บนเดสก์ท็อปได้ และเปิดใช้งานฟีเจอร์การควบคุมหน้าต่าง โดยคลิกเครื่องหมายบั้งที่มุมขวาบน

เครื่องคิดเลข Designcember Calculator ทำงานในโหมดสแตนด์อโลน โดยเปิดใช้งานฟีเจอร์การวางซ้อนการควบคุมหน้าต่างอยู่ การแสดงผลจะสะกดว่า &#39;Google&#39; ในตัวอักษรเครื่องคิดเลข

โซลาร์เซลล์ที่ใช้งานได้จริง

สำหรับผู้ที่อยากรู้อยากเห็น แน่นอนว่าฉันต้องทำให้โซลาร์เซลล์ทำงานได้จริงๆ เครื่องคำนวณควรจะทำงานเมื่อมีแสงเพียงพอเท่านั้น วิธีที่ผมใช้ในการสร้างแบบจำลองนี้คือการตั้งค่า 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