ডিজাইনসেম্বার ক্যালকুলেটর

উইন্ডো কন্ট্রোল ওভারলে এপিআই এবং অ্যাম্বিয়েন্ট লাইট সেন্সর এপিআই সহ ওয়েবে একটি সৌর ক্যালকুলেটর পুনরায় তৈরি করার একটি স্কিওমরফিক প্রচেষ্টা।

চ্যালেঞ্জ

আমি 1980-এর দশকের বাচ্চা। আমি যখন উচ্চ বিদ্যালয়ে ছিলাম তখন এমন একটি জিনিস যা সমস্ত রাগ ছিল সৌর ক্যালকুলেটর। আমাদের সকলকে স্কুলের দ্বারা একটি TI-30X সোলার দেওয়া হয়েছিল, এবং আমার কাছে 69-এর ফ্যাক্টোরিয়াল গণনা করে আমাদের ক্যালকুলেটরগুলিকে একে অপরের সাথে বেঞ্চমার্ক করার স্মৃতি রয়েছে, যা TI-30X পরিচালনা করতে পারে সর্বোচ্চ সংখ্যা। (গতির বৈচিত্রটি খুব পরিমাপযোগ্য ছিল, আমি এখনও কেন জানি না।)

এখন, প্রায় ২৮ বছর পর, আমি ভেবেছিলাম HTML, CSS এবং JavaScript-এ ক্যালকুলেটর পুনরায় তৈরি করা একটি মজাদার ডিজাইনসেম্বার চ্যালেঞ্জ হবে। খুব বেশি ডিজাইনার না হওয়ায়, আমি স্ক্র্যাচ থেকে শুরু করিনি, কিন্তু সাসজা সেবেলোসের একটি কোডপেন দিয়ে।

বামদিকে স্ট্যাক করা HTML, CSS এবং JS প্যানেল সহ CodePen ভিউ এবং ডানদিকে ক্যালকুলেটর প্রিভিউ।

এটি ইনস্টলযোগ্য করুন

একটি খারাপ শুরু না হলেও, আমি সম্পূর্ণ স্কিওমরফিক দুর্দান্ততার জন্য এটিকে পাম্প করার সিদ্ধান্ত নিয়েছি। প্রথম ধাপ ছিল এটিকে একটি PWA তৈরি করা যাতে এটি ইনস্টল করা যায়। আমি গ্লিচ-এ একটি বেসলাইন 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 ফোনে ফুলস্ক্রিনে চলছে ডিজাইনসেম্বার ক্যালকুলেটর।

ডেস্কটপের সাথে মিশ্রন

ডেস্কটপে, আমি ব্যবহার করতে পারি এমন একটি দুর্দান্ত বৈশিষ্ট্য রয়েছে: Window Controls Overlay , যা আমাকে অ্যাপ উইন্ডোর শিরোনাম বারে সামগ্রী রাখতে দেয়। প্রথম ধাপ হল ডিসপ্লে মোড ফলব্যাক সিকোয়েন্সকে ওভাররাইড করা যাতে এটি উপলব্ধ হলে প্রথমে 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();

এখন এই সমস্ত জায়গায়, আমি একটি ক্যালকুলেটর উইজেট পেয়েছি যা পুরানো স্কুলের উইন্যাম্প থিমগুলির মধ্যে একটি সহ ক্লাসিক উইন্যাম্পের মতো মনে হয়৷ আমি এখন অবাধে আমার ডেস্কটপে ক্যালকুলেটর রাখতে পারি এবং উপরের ডানদিকের কোণায় শেভরনে ক্লিক করে উইন্ডো নিয়ন্ত্রণ বৈশিষ্ট্য সক্রিয় করতে পারি।

ডিজাইনসেম্বার ক্যালকুলেটর সক্রিয় উইন্ডো কন্ট্রোল ওভারলে বৈশিষ্ট্য সহ স্বতন্ত্র মোডে চলছে। ডিসপ্লে ক্যালকুলেটর বর্ণমালায় 'Google' বানান করে।

একটি আসলে কাজ সৌর কোষ

চূড়ান্ত geekery জন্য, আমি অবশ্যই সৌর কোষ আসলে কাজ করতে হবে. পর্যাপ্ত আলো থাকলেই ক্যালকুলেটর কাজ করবে। আমি যেভাবে মডেল করেছি তা হল ডিসপ্লেতে ডিজিটের CSS opacity সেট করার মাধ্যমে একটি CSS ভেরিয়েবল --opacity যা আমি জাভাস্ক্রিপ্টের মাধ্যমে নিয়ন্ত্রণ করি।

:root {
  --opacity: 0.75;
}

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

ক্যালকুলেটর কাজ করার জন্য পর্যাপ্ত আলো পাওয়া যায় কিনা তা সনাক্ত করতে, আমি AmbientLightSensor API ব্যবহার করি। এই APIটি উপলব্ধ হওয়ার জন্য, আমাকে #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 সত্যিই একটি দীর্ঘ পথ এসেছে।

ডেমো

ডিজাইনসেম্বার ক্যালকুলেটর ডেমোর সাথে খেলতে ভুলবেন না এবং গ্লিচ-এ সোর্স কোডটি দেখুন। (অ্যাপটি ইনস্টল করতে, আপনাকে এটির নিজস্ব উইন্ডোতে খুলতে হবে। নীচের এম্বেড করা সংস্করণটি মিনি ইনফোবারকে ট্রিগার করবে না।)

শুভ ডিজাইনসেম্বর !