Kalendarz

barnat.net/portfolio/calendar

Potrzebowałem kalendarz który pozwoli badzo szybko przewijać miesiące bez podgrzewania procesora. Przetestowałem popularne biblioteki Moment oraz Luxon, efekty były słabe, więc napisałem wszystko sam w języku TypeScript.

Zmiana kolorów poprzez zmienne CSS sterowane przez JS.

function setTheme(t: colorDef): void {
 Object.keys(t).map(key => document.documentElement.style.setProperty(key, t[key]))
}
@mixin backgroundColor($color-name) {
  background-color: map-get($colors, $color-name);
  background-color: var(map-get($csscolors, $color-name));
}

Szybka reakcja na telefonie, bo efekt po zdarzeniu 'touchstart', a nie po 'click'

gist.github.com/jbarnat/debounce.ts

Możliwość wyboru dni poprzez zaznaczenie obszaru myszką.

Drobna optymalizacja: w pierwszym kroku wybieram miesiące które przecinają się z zaznaczonym obszarem, następnie sprawdzam wszystkie dni z wybranych miesięcy.

const m: HTMLElement[][] = Array.from(document.querySelectorAll('.monthSmall'))
  .filter(el => intersect(el.getBoundingClientRect(), markRect))
  .map(el => Array.from(el.querySelectorAll('.day')))

const days: HTMLElement[] = R.flatten(m).filter(el => overlap(markRect, el.getBoundingClientRect()))

Filtrowanie i przeliczanie liczebności podzbiorów

barnat.net/portfolio/filter/admin.html

Baza zawiera 20 tysięcy publikacji charakteryzowanych przez rok wydania, język, kraj, konferencję, wydawcę itp.

Niebieskie liczby widoczne przy każdej kategorii oznaczają liczbę publikacji które należą do danej kategorii.

Kliknięcie w kategorię powoduje nałożenie filtra na zbiór publikacji; następnie wyświetlenie pasujacych publikacji oraz aktualizację liczebności wszystkich kategorii.

Zastosowanie podobne do tabeli przestawnych w arkuszach kalkulacyjnych.

Przeliczanie odbywa się po stronie przeglądarki, zajmuje około 50ms, a cała strona zajmuje jedynie 3.8 MB pamięci RAM (Google Chrome)

// przygotowanie danych
const response = await fetch(dataUrl)
const buffer = await response.arrayBuffer()
Object.defineProperty(list[x], 'data', {
  value: new DataView(buffer, x * bytesPerVar, bytesPerVar)
})
// aktualizacja filtra
for (let offset = 0; offset < bytesPerVar; offset++) {
  let bitmask = list
    .filter(f => f.on)
    .map(f => f.data.getUint8(offset))
    .reduce((sum, c) => sum & c, -1)
  if (bitmask > 0) {
    for (let x = 7; x > -1; x--) {
      if (bitmask >> x & 1) {
        currentDocuments.add((offset * 8) + (7 - x))
      }
    }
    list.forEach(f => {
      let data = f.data.getUint8(offset)
      let share = data & bitmask
      if (share != 0) {
        for (let y = 7; y > -1; y--) {
          if (share >> y & 1) {
            f.currentPower++
          }
        }
      }
    })

  }
}

Wizualizacja przedmiotu 3d

barnat.net/portfolio/3d/

js, babylon.js

Tree from url paths

barnat.net/portfolio/makeTree