Designcember hesap makinesi

Window Controls Overlay API ve Ortam Işığı Sensörü API ile web'de güneş enerjili hesap makinesini yeniden oluşturmaya yönelik bir skeuomorfik girişim.

Yarışma

1980'lerde çocuktum. Ben lisedeyken güneş enerjili hesap makineleri çok popülerdi. Okul hepimize birer TI-30X SOLAR vermişti. TI-30X'in hesaplayabildiği en yüksek sayı olan 69'un faktöriyelini hesaplayarak hesap makinelerimizi birbirleriyle karşılaştırdığımızı sevgiyle hatırlıyorum. (Hız farkı çok belirgindi, nedenini hâlâ bilmiyorum.)

Şimdi, yaklaşık 28 yıl sonra, hesap makinesini HTML, CSS ve JavaScript'te yeniden oluşturmanın eğlenceli bir Designcember yarışması olacağını düşündüm. Tasarım konusunda pek iyi olmadığım için sıfırdan başlamadım. Sassja Ceballos'un CodePen'ini kullandım.

Solda üst üste yerleştirilmiş HTML, CSS ve JS panelleri, sağda ise hesap makinesi önizlemesi bulunan CodePen görünümü.

Yüklenebilir hale getirme

Kötü bir başlangıç olmasa da tam bir iskeomorfik muhteşemlik için biraz daha geliştirmeye karar verdim. İlk adım, yüklenebilmesi için PWA'ya dönüştürmekti.

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

Mobil cihazlarla uyum sağlama

Uygulama artık yüklenebilir olduğuna göre bir sonraki adım, uygulamanın işletim sistemi uygulamalarıyla mümkün olduğunca uyumlu olmasını sağlamaktır. Mobil cihazlarda bunu, web uygulaması manifestinde görüntüleme modunu fullscreen olarak ayarlayarak yapabilirim.

{
  "display": "fullscreen"
}

Kamera deliği veya çentiği olan cihazlarda, içeriğin tüm ekranı kaplaması için görüntü alanını ayarlamak uygulamanın muhteşem görünmesini sağlar.

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

Pixel 6 Pro telefonda tam ekran çalışan Designcember Hesap Makinesi.

Masaüstüyle uyum sağlama

Masaüstünde kullanabileceğim harika bir özellik var: Window Controls Overlay. Bu özellik, uygulama penceresinin başlık çubuğuna içerik eklememe olanak tanıyor. İlk adım, görüntüleme modu yedek sırasını geçersiz kılarak kullanılabilir olduğunda önce window-controls-overlay modunu kullanmaya çalışmasını sağlamaktır.

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

Bu, başlık çubuğunun etkili bir şekilde kaybolmasını sağlar ve içerik, başlık çubuğu yokmuş gibi başlık çubuğu alanına taşınır. Benim fikrim, iskeomorfik güneş hücresini başlık çubuğuna taşımak ve hesap makinesi kullanıcı arayüzünün geri kalanını buna göre aşağı taşımak. Bunu, titlebar-area-* ortam değişkenlerini kullanan bazı CSS'lerle yapabilirim. Tüm seçicilerin wco sınıfına sahip olduğunu göreceksiniz. Bu sınıf, birkaç paragraf sonra önemli hale gelecek.

#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);
}

Ardından, genellikle sürüklemek için kullandığım başlık çubuğu mevcut olmadığından hangi öğeleri sürüklenebilir hale getireceğime karar vermem gerekiyor. Klasik bir widget tarzında, düğmeler dışında tüm hesap makinesini (-webkit-)app-region: drag uygulayarak sürüklenebilir hale getirebilirim. Düğmelere ise (-webkit-)app-region: no-drag uygulayarak sürükleme için kullanılmalarını engelleyebilirim.

#calc_inside.wco,
#calc_solar_cell.wco {
  -webkit-app-region: drag;
  app-region: drag;
}

button {
  -webkit-app-region: no-drag;
  app-region: no-drag;
}

Son adım, uygulamayı pencere kontrolleri yer paylaşımı değişikliklerine duyarlı hale getirmektir. Gerçek bir progresif geliştirme yaklaşımında, bu özelliğin kodunu yalnızca tarayıcı desteklediğinde yüklerim.

if ('windowControlsOverlay' in navigator) {
  import('/wco.js');
}

Pencere kontrolleri yer paylaşımı geometrisi her değiştiğinde uygulamayı mümkün olduğunca doğal görünecek şekilde değiştiriyorum. Kullanıcı pencereyi yeniden boyutlandırdığında sık sık tetiklenebileceğinden bu etkinliği geciktirmek iyi bir fikirdir. Yani wco sınıfını bazı öğelere uyguluyorum. Böylece yukarıdaki CSS'im devreye giriyor ve tema rengini de değiştiriyorum. navigator.windowControlsOverlay.visible özelliğini kontrol ederek pencere kontrolleri yer paylaşımının görünür olup olmadığını algılayabilirim.

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();

Tüm bu ayarlardan sonra, eski tarz Winamp temalarından birini kullanan klasik Winamp'e benzeyen bir hesap makinesi widget'ı elde ediyorum. Artık hesap makinesini masaüstümde istediğim yere yerleştirebilir ve sağ üst köşedeki köşeli parantezi tıklayarak pencere kontrolleri özelliğini etkinleştirebilirim.

Designcember Hesap Makinesi, Pencere Kontrolleri Yerleşimi özelliği etkin olarak bağımsız modda çalışıyor. Ekranda, hesap makinesi alfabesiyle &quot;Google&quot; yazıyor.

Çalışan bir güneş pili

Tam bir teknoloji meraklısı olarak, güneş hücresinin gerçekten çalışmasını sağlamam gerekiyordu. Hesap makinesi yalnızca yeterli ışık varsa çalışmalıdır. Bunu, ekrandaki rakamların CSS opacity değerini JavaScript ile kontrol ettiğim bir CSS değişkeni --opacity aracılığıyla ayarlayarak modelledim.

:root {
  --opacity: 0.75;
}

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

Hesap makinesinin çalışması için yeterli ışık olup olmadığını tespit etmek amacıyla AmbientLightSensor API'sini kullanıyorum. Bu API'nin kullanılabilmesi için about:flags içinde #enable-generic-sensor-extra-classes işaretini ayarlamam ve 'ambient-light-sensor' iznini istemem gerekti. Daha önce olduğu gibi, API desteklendiğinde yalnızca ilgili kodu yüklemek için progresif geliştirme kullanıyorum.

if ('AmbientLightSensor' in window) {
  import('/als.js');
}

Sensör, yeni bir okuma mevcut olduğunda ambiyans ışığını lüks biriminde döndürür. Tipik ışık durumlarının değer tablosuna dayanarak lüks değerini 0 ile 1 arasında bir değere dönüştüren çok basit bir formül buldum. Bu değeri programatik olarak --opacity değişkenine atıyorum.

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();
  }
})();

Aşağıdaki videoda, odanın ışığını yeterince açtığımda hesap makinesinin nasıl çalışmaya başladığını görebilirsiniz. İşte bu kadar: Gerçekten çalışan, iskeomorfik bir güneş enerjili hesap makinesi. Eski dostum TI-30X SOLAR, gerçekten de uzun bir yol katetti.

Demo

Designcember Hesap Makinesi demosunu denemeyi ve GitHub'daki kaynak koduna göz atmayı unutmayın. (Uygulamayı yüklemek için kendi penceresinde açmanız gerekir. Aşağıdaki yerleştirilmiş sürüm, mini bilgi çubuğunu tetiklemez.)

Designcember'ınız kutlu olsun!