Designcember कैलकुलेटर

विंडो कंट्रोल ओवरले एपीआई और ऐंबियंट लाइट सेंसर एपीआई की मदद से, वेब पर सोलर कैलकुलेटर फिर से बनाने की एक छोटी सी कोशिश की गई है.

चुनौती

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

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

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

इसे इंस्टॉल करने लायक बनाएं

हालांकि, शुरुआत अच्छी नहीं थी, लेकिन मैंने फ़ैसला किया कि इसे अजीबोगरीब अंदाज़ में दिखाना चाहिए. सबसे पहले, इसे PWA बनाना था, ताकि इसे इंस्टॉल किया जा सके. मेरे पास Glitch पर बुनियादी PWA टेंप्लेट है जिसे कम समय में डेमो की ज़रूरत होने पर रीमिक्स किया जाता है. इसके सर्विस वर्कर को आपको कोई कोडिंग अवॉर्ड नहीं मिलेगा और यह बिलकुल प्रोडक्शन के लिए तैयार नहीं है. हालांकि, यह 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 पर सेट करके ऐसा किया जा सकता है.

{
  "display": "fullscreen"
}

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

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

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

डेस्कटॉप के साथ ब्लेंड किया जा रहा है

डेस्कटॉप पर, मैं एक बेहतरीन सुविधा का इस्तेमाल कर सकती हूं: विंडो कंट्रोल ओवरले की मदद से, कॉन्टेंट को ऐप्लिकेशन विंडो के टाइटल बार में डाला जा सकता है. सबसे पहले, डिसप्ले मोड के फ़ॉलबैक क्रम को बदलें, ताकि यह 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, जिसके साथ विंडो कंट्रोल ओवरले की सुविधा चालू है. डिस्प्ले पर कैलकुलेटर के अक्षर में &#39;Google&#39; लिखा हुआ दिखता है.

असल में काम कर रहा एक सोलर सेल

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

: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');
}

नई रीडिंग उपलब्ध होने पर, सेंसर आस-पास की रोशनी को lux यूनिट में दिखाता है. रोशनी की सामान्य स्थितियों की वैल्यू की टेबल के आधार पर, मुझे lux की वैल्यू को 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 डेमो को ज़रूर आज़माएं और Glitch पर सोर्स कोड देखें. (ऐप्लिकेशन इंस्टॉल करने के लिए, आपको उसे उसकी विंडो में खोलना होगा. नीचे एम्बेड किया गया वर्शन, मिनी जानकारी बार को ट्रिगर नहीं करेगा.)

डिज़ाइनमेर की शुभकामनाएं!