Canvas: Efekt przejścia - manipulowanie kanałem alpha

Opublikowano: 19.05.2022 - tagi: JavaScript Canvas Animacja Piksel

Poniżej przedstawiam kod takiego efektu:

HTML:

<canvas id="canvas" width="640" height="480"></canvas>

JavaScript:

    let start;
    const effectTime = 3000;
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');

    const draw = (timestamp) => {
        if (start === undefined) {
            start = timestamp;
        }
        const elapsed = timestamp - start;

        if (elapsed > effectTime) {
            start = timestamp; // restart animacji, zaczynamy od nowa
        }
				
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const w = imageData.width;
        const h = imageData.height;
        for (let y = h - 1; y >= 0; y--) {
            for (let x = 0; x < w; x++) {
                let index = (y * w + x) * 4;
                imageData.data[index + 3] = parseInt(255 * (elapsed / effectTime));
            }
        }

        ctx.putImageData(imageData, 0, 0);

        requestAnimationFrame(draw);
    }

    draw();

Do stworzenia tego efektu korzystam z techniki manipulowania pikselami.

Zmienna effectTime przechowuje czas w milisekundach, ile ma zająć cała animacja.

Za sam efekt przejścia odpowiada ta linijka:

imageData.data[index + 3] = parseInt(255 * (elapsed / effectTime));

Na samym początku animacji będziemy mieć pełną przeźroczystość (wartość równa zero lub bliska zeru). Wraz z upływem czasu przeźroczystość będzie maleć.

Jeśli chcemy uzyskać efekt odwrotny: czyli najpierw brak przeźroczystości, a na końcu pełna wystarczy napisać:

imageData.data[index + 3] = 255 - parseInt(255 * (elapsed / effectTime));

Canvas: Jak sprawdzić ile czasu upłyneło od momentu startu animacji?

Opublikowano: 17.05.2022 - tagi: JavaScript Canvas Animacja

Pisząc w Canvas w JavaScript do tworzenia animacji zaleca się używanie funkcji: requestAnimationFrame.

I za pomocą niej dowiemy się, ile upłynęło czasu od jej uruchomienia.

Ile upłynęło czasu od startu animacji?

Poniżej przykład:

  let start;
  const render = (timestamp) => {
    if (start === undefined) {
      start = timestamp;
    }
		
    const elapsed = parseInt((timestamp - start) / 1000);

    console.log(`elapsed: ${elapsed}`);
    requestAnimationFrame(render);
  }

  render();

Więc mamy funkcję render. Posiada ona jeden parametr: timestamp. To znacznik czasu, który będzie przekazany poprzez wywołanie funkcji requestAnimationFrame.

Przy pierwszym wywołaniu przypisujemy zmiennej start wartość. Jest to znacznik czasu pierwszego wywołania animacji. A później w zmiennej elapsed zapisujemy, ile czasu upłynęło od startu. Ponieważ znacznik czasu jest podany w milisekundach więc żeby wiedzieć ile to sekund, dzielimy różnicę między znacznikami przez 1000. 1 sekunda = 1000 milisekund.

Restart animacji

Załóżmy, że chcemy, żeby nasza animacji trwała 3 sekundy. Po upływie tego czasu chcemy zacząć wszystko od nowa. Oto przykład:

  let start;
  const animationTime = 3;
  const render = (timestamp) => {

    if (start === undefined) {
      start = timestamp;
    }

    const elapsed = parseInt((timestamp - start) / 1000);

    if (elapsed >= animationTime) {
      start = timestamp;
    }

    console.log(`elapsed: ${elapsed}`);
    requestAnimationFrame(render);
  }

  render();

Została dodana nowa zmienna animationTime, która przechowuje liczbę, mówiącą ile czasu ma trwać animacja. Sprawdzamy warunek: elapsed >= animationTime jeśli jest spełniony, to znaczy, że czas animacji się skończył, więc resetujemy znacznik czasu.

Tak na marginesie: nie tworzymy tutaj żadnej animacji. Ale możemy wykorzystać czas, jaki upłynął do stworzenia ciekawych efektów.


Comics: CRUD Dev - It ain't much but it's honest work

Opublikowano: 11.05.2022 - tagi: Komiks Rysowanie


Canvas: Manipulowanie pikselami podstawy

Opublikowano: 05.05.2022 - tagi: JavaScript Canvas Piksel

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: 03.05.2022 - tagi: JavaScript Losowanie Liczba Zakres

Ż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.