Designcember Hesap Makinesi

Pencere Kontrolü Yerleşimi API'si ve Ortam Işığı Sensörü API'si ile web'de güneş enerjisi hesap makinesini yeniden oluşturmaya yönelik skeomorfik bir girişim.

Yarışma

1980'lerde büyüdüm. Lisedeyken çok popüler olan bir şey vardı: güneş enerjili hesap makineleri. Okulda hepimize TI-30X SOLAR verilmişti. TI-30X'in işleyebileceği en yüksek sayı olan 69'un faktöriyelini hesaplayarak hesap makinelerimizi birbirleriyle karşılaştırdığımız günleri özlemle hatırlıyorum. (Hız farkı çok ölçülebilirdi, nedenini hâlâ bilmiyorum.)

Aradan geçen 28 yılın ardından, hesap makinesini HTML, CSS ve JavaScript ile yeniden oluşturmanın eğlenceli bir Designcember meydan okuması olacağını düşündüm. Tasarımcı 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 anlamıyla skeomorfik bir tasarım için daha da geliştirmeye karar verdim. İlk adım, yüklenebilmesi için PWA haline getirmekti.

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 cihazla harmanlama

Uygulama yüklenebilir hale geldiğine 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, web uygulaması manifestinde görüntüleme modunu fullscreen olarak ayarlayarak bunu yapabilirim.

{
  "display": "fullscreen"
}

Kamera deliği veya çentik bulunan cihazlarda, içeriğin ekranın tamamını kaplayacak şekilde görünüm alanını ayarlamak uygulamanın harika görünmesini sağlar.

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

Pixel 6 Pro telefonda tam ekran olarak çalışan Designcember Calculator.

Masaüstüyle uyum sağlama

Masaüstünde kullanabileceğim harika bir özellik var: Pencere Denetimi Yer Paylaşımı. Bu özellik sayesinde, uygulama penceresinin başlık çubuğuna içerik yerleştirebiliyorum. İlk adım, ekran modu yedekleme sırasını geçersiz kılmaktır. Böylece, window-controls-overlay kullanılabilir olduğunda önce bu mod kullanılmaya çalışılır.

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

Bu durumda başlık çubuğu etkili bir şekilde kaybolur ve içerik, başlık çubuğu yokmuş gibi başlık çubuğu alanına taşınır. Fikrim, skeomorfik güneş pilini başlık çubuğuna, hesap makinesi kullanıcı arayüzünün geri kalanını da buna göre aşağıya taşımak. Bunu, titlebar-area-* ortam değişkenlerini kullanan bazı CSS'lerle yapabilirim. Tüm seçicilerin wco sınıfı taşıdığını fark edeceksiniz. Bu sınıf, birkaç paragraf aşağıda ele alınacaktır.

#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, normalde sürüklemek için kullandığım başlık çubuğu mevcut olmadığından hangi öğelerin sürüklenebilir olacağına karar vermem gerekiyor. Klasik bir widget tarzında, düğmeler hariç tüm hesap makinesini (-webkit-)app-region: drag uygulayarak sürüklenebilir hale getirebilirim. Düğmeler (-webkit-)app-region: no-drag olarak ayarlanır, böylece sürüklemek için kullanılamazlar.

#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, uygulamanın pencere denetimi yer paylaşımı değişikliklerine tepki vermesini sağlamaktır. Gerçek bir aşamalı 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 kontrollerinin yerleşimi her değiştiğinde, uygulamanın mümkün olduğunca doğal görünmesi için değişiklik yapıyorum. Kullanıcı pencereyi yeniden boyutlandırdığında bu etkinlik sık sık tetiklenebileceğinden bu etkinliğin sıçrama önleme özelliğini kullanmanız önerilir. Yani bazı öğelere wco sınıfını uyguluyorum. Böylece yukarıdaki CSS'm devreye giriyor ve tema rengini de değiştiriyorum. Pencere kontrolleri yer paylaşımının görünür olup olmadığını navigator.windowControlsOverlay.visible özelliğini kontrol ederek 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 bunları yaptıktan sonra, klasik Winamp'a benzeyen bir hesap makinesi widget'ı ve eski tarz Winamp temalarından birini kullanabiliyorum. Artık hesap makinesini masaüstüme istediğim gibi yerleştirebiliyor ve sağ üst köşedeki açılı işareti tıklayarak pencere kontrolleri özelliğini etkinleştirebiliyorum.

Pencere denetimi yer paylaşımı özelliği etkin olarak bağımsız modda çalışan Designcember Hesap Makinesi. Ekranda hesap makinesi alfabesiyle &quot;Google&quot; yazıyor.

Gerçekten çalışan bir güneş pili

Elbette, en büyük geek'lik için güneş pilinin gerçekten çalışmasını sağlamam gerekiyordu. Hesap makinesi yalnızca yeterli ışık varsa çalışmalıdır. Bunu, JavaScript aracılığıyla kontrol ettiğim bir CSS değişkeni --opacity üzerinden ekrandaki rakamların CSS'sini opacity ayarlayarak yaptım.

:root {
  --opacity: 0.75;
}

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

Hesap makinesinin çalışması için yeterli ışık olup olmadığını algılamak 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 gerekiyordu. Daha önce olduğu gibi, API desteklendiğinde yalnızca alakalı kodu yüklemek için aşamalı geliştirme kullanıyorum.

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

Sensör, yeni bir okuma olduğunda ortam ışığını lüks birimleriyle 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ürmek için çok basit bir formül oluşturdum. Bu değeri --opacity değişkenine programatik olarak 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, oda ışığını yeterince açtığımda hesap makinesinin nasıl çalışmaya başladığını görebilirsiniz. İşte bu kadar. Gerçekten çalışan bir skeomorfik güneş enerjili hesap makinesi. Eski ve güvenilir TI-30X SOLAR hesap makinem gerçekten çok yol katetti.

Demo

Designcember Calculator demosunu incelemeyi 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.)

Mutlu Designcember!