Prezentacja: Canvas Paint Tutorial

Filip Gębala, Kamil Pawłowski, Henryk Rachtan

1. Struktura HTML

Definiujemy podstawowe elementy aplikacji:

<!DOCTYPE html>
<html lang="pl">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas Paint</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="controls">
    <button id="brushToolButton">Brush</button>
    <button id="pathToolButton">Start Path Drawing</button>
    <input type="color" id="colorPicker" value="#000000">
    <div class="brush-size-container">
      <label for="brushSize">Brush Size: <span id="brushSizeValue">5</span></label>
      <input type="range" id="brushSize" min="1" max="50" value="5">
    </div>
    <button id="clearCanvasButton">Clear Canvas</button>
  </div>
  <canvas id="paintCanvas"></canvas>
  <script src="script.js"></script>
</body>
</html>

2. Style CSS

Stosujemy ciemny motyw dla kontrolek i jasne tło dla kodu oraz responsywność:

body {
  background: linear-gradient(135deg, #1e1e2e, #2d2d42);
  font-family: 'Segoe UI', sans-serif;
  color: #e8e8e8;
}
.controls {
  background: rgba(45,45,66,0.8);
  backdrop-filter: blur(10px);
  padding: 20px;
  border-radius: 15px;
  display: flex;
  gap: 15px;
}
button {
  background: linear-gradient(145deg, #3a3a52, #2d2d42);
  border: none;
  color: #e8e8e8;
  padding: 10px 16px;
  border-radius: 8px;
  cursor: pointer;
}
#paintCanvas {
  border: 2px solid rgba(255,255,255,0.2);
  background: #ffffff;
  display: block;
  margin: 20px auto;
}

3. Inicjalizacja Canvas

Pobieramy element <canvas> i ustawiamy kontekst oraz wymiary:

const canvas = document.getElementById('paintCanvas');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 400;

4. Zmienne globalne i narzędzia

Przechowujemy stan narzędzi, kolor, rozmiar pędzla i punkty ścieżki:

let currentTool = 'brush';
let isPainting = false;
let currentColor = '#000000';
let currentBrushSize = 5;
let pathPoints = [];

5. Obsługa interakcji

Reakcja na zmiany koloru, rozmiaru pędzla i wybór narzędzia:

colorPicker.addEventListener('change', e => currentColor = e.target.value);
brushSizeInput.addEventListener('input', e => {
  currentBrushSize = e.target.value;
  brushSizeValue.textContent = currentBrushSize;
});
brushToolButton.addEventListener('click', () => currentTool = 'brush');
pathToolButton.addEventListener('click', togglePathTool);
clearCanvasButton.addEventListener('click', clearCanvas);

6. Mechanizm rysowania pędzlem

Rysujemy linię podczas przesuwania myszy (mousedown → mousemove → mouseup):

function handleMouseDown(e) {
  if (currentTool === 'brush') {
    isPainting = true;
    const { x, y } = getMousePos(e);
    ctx.beginPath(); ctx.moveTo(x, y);
  }
}

function handleMouseMove(e) {
  if (currentTool === 'brush' && isPainting) {
    const { x, y } = getMousePos(e);
    ctx.lineTo(x, y);
    ctx.strokeStyle = currentColor;
    ctx.lineWidth = currentBrushSize;
    ctx.lineCap = 'round';
    ctx.stroke();
    ctx.beginPath(); ctx.moveTo(x, y);
  }
}

function handleMouseUp() { isPainting = false; }

canvas.addEventListener('mousedown', handleMouseDown);
canvas.addEventListener('mousemove', handleMouseMove);
canvas.addEventListener('mouseup', handleMouseUp);

Zadanie

Na podstawie powyższego kodu stwórz gumkę

7. Mechanizm rysowania ścieżek

Dodajemy punkty za pomocą kliknięć i łączymy je liniami:

function togglePathTool() {
  currentTool = currentTool === 'path' ? 'brush' : 'path';
  pathPoints = [];
}

function handleMouseDown(e) {
  if (currentTool === 'path') {
    const { x, y } = getMousePos(e);
    pathPoints.push({ x, y });
    if (pathPoints.length > 1) {
      const prev = pathPoints[pathPoints.length - 2];
      ctx.beginPath();
      ctx.moveTo(prev.x, prev.y);
      ctx.lineTo(x, y);
      ctx.stroke();
    }
    drawPathPointMarker(x, y);
  }
}

canvas.addEventListener('mousedown', handleMouseDown);

8. Czyszczenie płótna

Wyczyść cały rysunek i zresetuj punkty ścieżki:

function clearCanvas() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  pathPoints = [];
}