Vytvořte aplikaci pro kreslení pomocí JavaScriptu a plátna

V tomto tutoriálu vytvoříme jednoduchou aplikaci pro kreslení v prohlížeči. K tomu použijeme vanilla JS a API Canvas.
Po tomto tutoriálu budete mít skvělý přehled o canvas API a zpracování událostí v javascriptu.

Video tutoriál

Pokud byste se podívali na podrobný krok za krokem video místo toho se můžete podívat na video, které jsem natočil o tomto projektu na mém Youtube kanálu:

Označení HTML

Začneme zabalením celé aplikace do section s třídou container . To se použije k zarovnání panelu nástrojů a kreslicího prkna.

Uvnitř vytvoříme div který bude držet náš panel nástrojů. Také jsem nastavil id toolbar proto bude snazší s ním pracovat v javascriptu.

Do panelu nástrojů přidáme název naší aplikace v h1 . Pod to přidáme dvě vstupní pole:jedno pro barvu a jedno pro s čárou. Pro barevný vstup přidám id stroke protože bude definovat barvu tahu a pro zadání čísla přidám id lineWidth . Nezapomeňte přidat odpovídající štítky pro tato vstupní pole. Nakonec přidám tlačítko s id clear a to se použije k vyčištění rýsovacího prkna.

Další věc, kterou musíme přidat do našeho html, je skutečné rýsovací prkno. Bude to canvas prvek, ale pro účely rozvržení jej zabalíme do div .

Nakonec musíme přidat značku skriptu pro náš skript na konec body .

<section class="container">
  <div id="toolbar">
        <h1>Draw.</h1>
        <label for="stroke">Stroke</label>
        <input id="stroke" name='stroke' type="color">
        <label for="lineWidth">Line Width</label>
        <input id="lineWidth" name='lineWidth' type="number" value="5">
        <button id="clear">Clear</button>
    </div>
    <div>
        <canvas id="drawing-board"></canvas>
    </div>
</section>
<script src="./index.js"></script>

Přidejte styly pomocí CSS

Začnu tím, že odstraním v prohlížeči definované výplně a okraje. Nastavte také výšku těla na 100 % a odstraňte posuvník pomocí overflow: hidden.

body {
    margin: 0;
    padding: 0;
    height: 100%;
    overflow: hidden;
    color: white;
}

Pro nadpis přidám barvu přechodového textu.

h1 {
    background: #7F7FD5;
    background: -webkit-linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5);
    background: linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

Uděláme také 100% výšku kontejneru, nastavíme displej na ohyb.

.container {
    height: 100%;
    display: flex;
}

Pro panel nástrojů použijeme flexbox se směrem sloupců. Šířka panelu nástrojů bude mít pevnou šířku 70 pixelů. Přidáme mezery s 5px odsazením a nastavíme pro to tmavé pozadí.

Pro prvky panelu nástrojů aplikuji základní styling. Neváhejte a zkopírujte tyto styly 👇

#toolbar {
    display: flex;
    flex-direction: column;
    padding: 5px;
    width: 70px;
    background-color: #202020;
}

#toolbar * {
    margin-bottom: 6px;
}

#toolbar label {
    font-size: 12px;
}

#toolbar input {
    width: 100%;
}

#toolbar button {
    background-color: #1565c0;
    border: none;
    border-radius: 4px;
    color:white;
    padding: 2px;
}

Implementace části javascript.

Nejprve si uložíme reference pro panel nástrojů a kreslicí prkno (plátno).

const canvas = document.getElementById('drawing-board');
const toolbar = document.getElementById('toolbar');

Dále musíme získat kontext plátna. Tento kontext použijeme ke kreslení na plátno. Můžeme to udělat voláním getContext metoda plátna. Budeme kreslit ve 2D, takže to musíme zadat jako parametr.

const ctx = canvas.getContext('2d');

V dalším kroku shromáždíme ofsety (vzdálenost mezi okraji plátna k okraji výřezu) a uložíme je. V tomto případě bude horní odsazení 0px, protože plátno zabere celou výšku výřezu, a odsazení vlevo bude 70px, protože vlevo máme postranní panel s pevnou šířkou. Dále vypočítáme a nastavíme výšku a šířku plátna odečtením offsetů od šířky a výšky výřezu.

const canvasOffsetX = canvas.offsetLeft;
const canvasOffsetY = canvas.offsetTop;

canvas.width = window.innerWidth - canvasOffsetX;
canvas.height = window.innerHeight - canvasOffsetY;

Nyní nastavíme nějaké globální proměnné. isPainting proměnná bude odrážet, zda právě kreslíme nebo ne. Nastavíme základní šířku čáry 5 px. Nakonec deklarujeme dvě proměnné (startX &startY), které budou obsahovat souřadnice bodu, ze kterého jsme začali kreslit.

let isPainting = false;
let lineWidth = 5;
let startX;
let startY;

Začněme nyní přidávat posluchače událostí. Nejprve na panel nástrojů přidáme posluchač události kliknutí. Pokud e.target.id je jasné (takže bylo kliknuto na tlačítko Clear), pak zavoláme clearRect funkci a poskytnout jí šířku a výšku plátna. Tato metoda v podstatě nastaví každý pixel plátna na bílý uvnitř zadaných hodnot šířky a výšky (takže v tomto případě celého plátna).

toolbar.addEventListener('click', e => {
    if (e.target.id === 'clear') {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
});

Dále se budeme zabývat změnami vstupu pro šířku čáry a barvu kresby. V tomto případě použijeme delegování události. Takže namísto definování samostatných obslužných rutin událostí pro každé vstupní pole přidáme do nadřazeného prvku pouze jeden posluchač událostí a budeme události zpracovávat odtud. Můžeme rozlišit, které vstupní pole bylo změněno kontrolou hodnoty e.target . Pokud byla barva změněna, nastavíme strokeStyle kontextu plátna, pokud se změnila šířka řádku, aktualizujeme hodnotu globálního lineWidth proměnná s novou hodnotou.

toolbar.addEventListener('change', e => {
    if(e.target.id === 'stroke') {
        ctx.strokeStyle = e.target.value;
    }

    if(e.target.id === 'lineWidth') {
        lineWidth = e.target.value;
    }
});

Dále implementujeme ovládací prvky kreslení. Když dojde k události mousedown (uživatel klikne a podrží tlačítko myši), nastavíme isPainting proměnná na true a souřadnice aktuální pozice myši nastavíme na startX a startY .

Pokud uživatel pustí tlačítko myši, nastavíme isPainting na hodnotu false a zavolejte stroke metoda kontextu pro obarvení již nakreslené cesty. Musíme také zavolat beginPath metoda k uzavření cesty, kterou uživatel dosud nakreslil. Musíme to udělat, protože pokud chce uživatel nakreslit další čáru, začne od této pozice, a to není něco, co chceme.

Nakonec do události mousemove přidáme posluchač události. Když uživatel pohne myší, zavoláme funkci draw, kterou implementujeme jako další.

canvas.addEventListener('mousedown', (e) => {
    isPainting = true;
    startX = e.clientX;
    startY = e.clientY;
});

canvas.addEventListener('mouseup', e => {
    isPainting = false;
    ctx.stroke();
    ctx.beginPath();
});

canvas.addEventListener('mousemove', draw);

V draw nejprve zkontrolujeme hodnotu isPainting proměnná, pokud je false, nekreslíme, takže jednoduše zavoláme return.

Dále nastavíme šířku čáry tak, aby převzala hodnotu z globální proměnné a nastavíme lineCap na zaokrouhlení. Poté nakreslíme čáru voláním lineTo metoda se souřadnicemi aktuální polohy myši. Jedna věc, na kterou musíte být opatrní, je odečíst posun od souřadnice X, protože jinak by byla nakreslená čára posunuta o šířku postranního panelu (70px). Nakonec musíme zavolat pouze stroke způsob, jak dát čáře barvu, kterou jsme vybrali.

const draw = (e) => {
    if(!isPainting) {
        return;
    }

    ctx.lineWidth = lineWidth;
    ctx.lineCap = 'round';

    ctx.lineTo(e.clientX - canvasOffsetX, e.clientY);
    ctx.stroke();
}

A to je vše, nyní máte funkční aplikaci pro kreslení!

Pokud jste někde uvízli, můžete se podívat na video nebo se můžete podívat na zdrojový kód na Codepen.

Kde se ode mě můžete dozvědět více?

Tvořím vzdělávací obsah pokrývající vývoj webu na několika platformách, neváhejte se na ně 👀 podívat.

Vytvářím také newsletter, kde sdílím týdenní nebo 2týdenní vzdělávací obsah, který jsem vytvořil. Žádný bull💩 jen vzdělávací obsah.

🔗 Odkazy:

  • 🍺 Podpořte bezplatné vzdělávání a kupte mi pivo
  • 💬 Připojte se k naší komunitě na Discordu
  • 📧 Newsletter Přihlaste se k odběru zde
  • 🎥 YouTube Javascript Academy
  • 🐦 Twitter:@dev_adamnagy
  • 📷 Instagram @javascriptacademy