Designcember कैलकुलेटर

Window Controls Overlay API और स्क्रीन की रोशनी को अपने-आप घटाने-बढ़ाने वाले सेंसर के एपीआई की मदद से, वेब पर सोलर कैलकुलेटर को फिर से बनाने की एक स्क्यूमॉर्फ़िक कोशिश.

चुनौती

मैं 1980 के दशक का बच्चा हूं. जब मैं हाई स्कूल में था, तब सौर ऊर्जा से चलने वाले कैलकुलेटर काफ़ी लोकप्रिय थे. स्कूल ने हम सभी को एक TI-30X SOLAR दिया था. मुझे याद है कि हम अपने कैलकुलेटर की तुलना एक-दूसरे से करते थे. इसके लिए, हम 69 का फ़ैक्टोरियल निकालते थे. यह सबसे बड़ी संख्या थी जिसे TI-30X हैंडल कर सकता था. (स्पीड में अंतर को आसानी से मापा जा सकता था, मुझे अब भी नहीं पता कि ऐसा क्यों था.)

अब करीब 28 साल बाद, मुझे लगा कि Designcember चैलेंज के तौर पर, एचटीएमएल, सीएसएस, और JavaScript में कैलकुलेटर को फिर से बनाना मज़ेदार होगा. मैं कोई डिज़ाइनर नहीं हूं, इसलिए मैंने शुरुआत से काम नहीं किया, बल्कि Sassja Ceballos के CodePen से शुरुआत की.

CodePen व्यू में, बाईं ओर एचटीएमएल, सीएसएस, और JS पैनल स्टैक किए गए हैं. वहीं, दाईं ओर कैलकुलेटर की झलक दिख रही है.

इसे इंस्टॉल किया जा सकता है

यह शुरुआत के लिए बुरा नहीं था, लेकिन मैंने इसे और बेहतर बनाने का फ़ैसला किया, ताकि यह पूरी तरह से स्क्यूमॉर्फ़िक लगे. सबसे पहले, इसे PWA बनाया गया, ताकि इसे इंस्टॉल किया जा सके.

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 पर सेट करके ऐसा किया जा सकता है.

{
  "display": "fullscreen"
}

कैमरा होल या नॉच वाले डिवाइसों पर, व्यूपोर्ट में बदलाव करें, ताकि कॉन्टेंट पूरी स्क्रीन पर दिखे. इससे ऐप्लिकेशन शानदार दिखता है.

<meta name="viewport" content="initial-scale=1, viewport-fit=cover" />

Pixel 6 Pro फ़ोन पर फ़ुलस्क्रीन में चल रहा Designcember Calculator.

डेस्कटॉप के साथ ब्लेंड करना

डेस्कटॉप पर, एक शानदार सुविधा है जिसका इस्तेमाल किया जा सकता है: Window Controls Overlay. इसकी मदद से, ऐप्लिकेशन विंडो के टाइटल बार में कॉन्टेंट डाला जा सकता है. सबसे पहले, डिसप्ले मोड के फ़ॉलबैक क्रम को बदलें, ताकि उपलब्ध होने पर यह सबसे पहले window-controls-overlay का इस्तेमाल करे.

{
  "display_override": ["window-controls-overlay"]
}

इससे टाइटल बार हट जाता है और कॉन्टेंट, टाइटल बार वाले हिस्से में ऊपर की ओर चला जाता है. ऐसा लगता है कि टाइटल बार मौजूद ही नहीं है. मेरा आइडिया है कि स्क्यूमॉर्फ़िक सोलर सेल को टाइटल बार में ऊपर ले जाऊं और कैलकुलेटर के बाकी यूज़र इंटरफ़ेस (यूआई) को उसके हिसाब से नीचे ले जाऊं. इसके लिए, मैं कुछ सीएसएस का इस्तेमाल कर सकता हूं, जो 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 क्लास लागू करता हूं, ताकि ऊपर दी गई सीएसएस लागू हो जाए. साथ ही, मैं थीम का रंग भी बदलता हूं. 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, विंडो कंट्रोल ओवरले की सुविधा चालू होने पर, स्टैंडअलोन मोड में चल रहा है. डिसप्ले पर, कैलकुलेटर के अक्षरों में 'Google' लिखा हुआ है.

काम करने वाला सोलर सेल

इस प्रोजेक्ट को और भी शानदार बनाने के लिए, मुझे सोलर सेल को असल में काम करने लायक बनाना था. कैलकुलेटर सिर्फ़ तब काम करना चाहिए, जब रोशनी काफ़ी हो. मैंने इसे इस तरह से मॉडल किया है: मैंने JavaScript से कंट्रोल किए जाने वाले सीएसएस वैरिएबल --opacity की मदद से, डिसप्ले पर मौजूद अंकों के सीएसएस opacity को सेट किया है.

:root {
  --opacity: 0.75;
}

#calc_expression,
#calc_result {
  opacity: var(--opacity);
}

कैलकुलेटर को काम करने के लिए ज़रूरी रोशनी मिल रही है या नहीं, इसका पता लगाने के लिए मैं AmbientLightSensor एपीआई का इस्तेमाल करता हूं. इस एपीआई को उपलब्ध कराने के लिए, मुझे about:flags में #enable-generic-sensor-extra-classes फ़्लैग सेट करना पड़ा और 'ambient-light-sensor' की अनुमति का अनुरोध करना पड़ा. पहले की तरह, मैं प्रोग्रेसिव एन्हांसमेंट का इस्तेमाल करता हूं, ताकि एपीआई के काम करने पर सिर्फ़ काम का कोड लोड हो.

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 Calculator का डेमो ज़रूर आज़माएं और GitHub पर सोर्स कोड देखें. ऐप्लिकेशन इंस्टॉल करने के लिए, आपको इसे अपनी विंडो में खोलना होगा. नीचे दिया गया एम्बेड किया गया वर्शन, मिनी जानकारी बार को ट्रिगर नहीं करेगा.)

Designcember की शुभकामनाएं!