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

การพยายามสร้างเครื่องคำนวณพลังงานแสงอาทิตย์ขึ้นมาใหม่บนเว็บด้วย Window Controls Overlay API และ Ambient Light Sensor API

ความท้าทาย

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

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

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

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

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

เครื่องคิดเลข Designcember ที่ทำงานแบบเต็มหน้าจอในโทรศัพท์ Pixel 6 Pro

การผสานรวมกับเดสก์ท็อป

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

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

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

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