Canvas: Manipulowanie pikselami podstawy

Opublikowano: - tagi:

Canvas API udostępnia zbiór funkcji do manipulowania danymi obrazu na poziomie pikseli.

Dostęp do danych tak niskiego poziomu sprawia, że możemy zaimplementować wiele ciekawych efektów.

Pobieranie danych o pikselach

Do pobrania danych o pikselach wystarczy wywołać metodę getImageData:

getImageData(sx, sy, sw, sh)

Wywołujemy ją z kontekstu Canvas. Przyjmuje cztery parametry:

Dwa pierwsze parametry: sx i sy określają lewy-górny punkt startowy, od którego ma pobrać dane o pikselach. Dwa ostatnie parametry sw i sh to odpowiednio szerokość i wysokość obszaru, z którego mają zostać pobrane dane o pikselach.

Metoda getImageData zwraca obiekt o nazwie: ImageData, który posiada takie właściwości:

width - Szerokość obszaru, dla którego zostały pobrane piksele.
height - Wysokość obszaru, dla którego zostały pobrane piksele.
data - Tutaj znajduje się to, co nas interesuje. Czyli tablica wszystkich pikseli.

data jest to jednowymiarowa tablica. Każdy piksel jest opisany przez cztery wartości: RGBA: R - red (czerwony), G - green (zielony), B - blue (niebieski), i A - aplha dla kanału alfa.

Inaczej mówiąc jeśli chcemy mieć dostęp do pierwszego piksela, piszemy:

imageData[0] = 128; // czerwony
imageData[1] = 64; // zielony
imageData[2] = 250; // niebieski
imageData[3] = 128; // kanał alfa

Każdy element z data przyjmuje wartość z przedziału: 0 - 255. W przypadku kanału alfa 255 oznacza brak przezroczystości a 0 pełną przezroczystość.

Zapis zmodyfikowanych pikseli

Skoro już wiem, jak pobrać piksele to czas nauczyć się, jak zastosować wprowadzone przez nas zmiany na płótnie.

Służy do tego metoda putImageData:

putImageData(imageData, dx, dy)

W pierwszym parametrze imageData przekazujemy tablicę pikseli, które chcemy zastosować. Ostatnie dwa parametry to punkt startowy, od którego mają zostać zapisane zmiany.

Przykład

To teraz czas zebrać całą wiedzę tutaj opisaną:

Dodaj element canvas w pliku HTML:

<canvas id="canvas" width="800" height="600"></canvas>

I wreszcie kod w JavaScript:

  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  const randomRange = (min, max) => Math.floor(min + Math.random() * (max - min + 1));

  const draw = () => {
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const width = imageData.width;
    const height = imageData.height;

    for (let y = 0; y < height; y++) {
      for (let x = 0; x < width; x++) {
        const index = (y * width + x) * 4;
        const color = randomRange(0, 255);
        // Ustaw wartości dla pojedynczego piksela
        imageData.data[index] = color; // R
        imageData.data[index + 1] = color; // G
        imageData.data[index + 2] = color; // B
        imageData.data[index + 3] = 255; // A
      }
    }
    ctx.putImageData(imageData, 0, 0);
  }
  const render = () => {
    draw();
    requestAnimationFrame(render);
  }

  render();

Ten kod tworzy animację szumu. Zmieniamy każdy piksel obrazu.

Zapis:

const index = (y * width + x) * 4;

Daje nam dostęp do pojedynczego piksela. Następnie ustawiamy wartości dla każdego piksela. Po modyfikacji całej tablicy zapisujemy zmiany dla pierwszej klatki animacji.


JavaScript: Jak wylosować liczbę z podanego zakresu?

Opublikowano: - tagi:

Żeby wylosować liczbę z zakresu: (1, 10) wystarczy napisać:

const randomRange = (min, max) => Math.floor(min + Math.random() * (max - min + 1));

console.log(randomRange(1, 10)); // 6 
console.log(randomRange(1, 10)); // 10
console.log(randomRange(1, 10)); // 1

Funkcja, w takiej postaci może zwrócić liczbę minimum lub maksimum z podanego zakresu.


Podsumowanie: Kwiecień 2022

Opublikowano: - tagi:

W kwietniu opublikowałem 6 wpisów:

Inne:

  1. Blog: Podsumowanie po roku

NodeJS:

  1. Mongoose jak sprawdzić czy podano tablicę w modelu danych?

JavaScript:

  1. RxJS: Operator pluck
  2. Jak usunąć duplikaty z tablicy?
  3. TypeScript: Omit

MongoDB:

  1. Jak sprawdzić czy pole ma daną wartość lub null?

Przeczytałem dwie książki:

  1. Czerwona kraina - Joe Abercrombie
  2. Shitshow!. Ameryka się sypie, a oglądalność szybuje - Charlie LeDuff

Przesłuchałem trzy audiobooki:

  1. 21 lekcji na XXI wiek - Yuval Noah Harari
  2. Okruchy dnia - Kazuo Ishiguro
  3. Dygot - Jakub Małecki

TypeScript: Omit

Opublikowano: - tagi:

Omit tworzy nowy typ danych na podstawie już istniejącego. Przydaje się szczególnie wtedy kiedy chcemy się pozbyć niektórych pól ze wzorca.

Składania wygląda następująco:

Omit<Type, Keys>

Pierwszy parametr Type to istniejący typ danych. Drugi: Keys to pole lub pola, które nie zostaną wzięte pod uwagę, w nowo stworzonym typie danych.

Jest dostępny w TypeScript od wersji 3.5

Przykłady

Przykład 1

interface Book {
	title: string;
	author: string;
	pages: number;
}

type AudioBook = Omit<Book, 'pages'>;

// AudioBook będzie wyglądać tak:
/*
AudioBook {
	title: string;
	author: string;
}
*/

Mamy nowy typ AudioBook bez pola pages.

Przykład 2

Jeśli chcemy pozbyć się więcej niż jedno pole, piszemy:

interface Book {
	title: string;
	author: string;
	pages: number;
	weight: number;
}

type eBook = Omit<Book, 'pages' | 'weight'>;

// eBook będzie wyglądać tak:
/*
eBook {
	title: string;
	author: string;
}
*/

Przykład 3

Za pomocą Omit możemy także rozszerzać interfejsy:

interface Book {
	title: string;
	author: string;
	pages: number;
	weight: number;
}

interface AudioBook extends Omit<Book, 'pages' | 'weight'> {
	length: number;
}

// Interfejs AudioBook będzie wyglądać tak:
/*
interface AudioBook {
	title: string;
	author: string;
	length: number;
}
*/

Przykład 4

Dzięki Omit możemy też "nadpisać" dane pole:

interface Book {
	id: string;
	title: string;
	author: string;
}

interface AudioBook extends Omit<Book, 'id'> {
	id: number;
}

// Interfejs AudioBook będzie wyglądać tak:
/*
interface AudioBook {
	id: number;
	title: string;
	author: string;
}
*/

W interfejsie Book mamy pole id o typie string. A w nowym typie AudioBook potrzebujemy wszystkie pola z Book tylko pole id powinno być typu number. Dzięki Omit jak widać, można to łatwo osiągnąć.


MongoDB: Jak sprawdzić czy pole ma daną wartość lub null?

Opublikowano: - tagi:

Załóżmy, że mamy taki model danych:

{
	title: string,
	status: string | null
}

Poniżej przykład danych na podstawie tego modelu:

[
	{
		title: "Status Draft"
		status: "draft"
	}
	{
		title: "Status Null"
		status: null
	},
	{
		title: "Status Closed"
		status: "closed"
	}
]

I teraz potrzebujemy napisać zapytanie, które pobierze nam dane na podstawie pola status: pobierz rekordy dla wartości X lub dla null.

Wystarczy napisać:

db.find({
  $or: [
		{ 
			status: { $eq: 'draft' }
		},
		{
			status: { $type: 'null' } 
		}
	]
})

Korzystamy tutaj z operatora $or: sprawdzamy najpierw, czy istnieją rekordy o podanej wartości i dodatkowo informujemy za pomocą $type, że chcemy pobrać także rekordy z wartością null.

W tym przypadku zwróci dwa rekordy:

[
	{
		title: "Status Draft"
		status: "draft"
	}
	{
		title: "Status Null"
		status: null
	}
]