{}const=>[]async()letfn</>var
WebEntwicklung

Wir erstellen eine Zeichen-App in HTML, CSS und JavaScript

Eine Webseiten-Zeichen-App ist eine großartige Möglichkeit, um mit HTML, CSS und JavaScript zu üben und interaktive Tools zu erstellen

К

Kodik

Autor

10 Min. Lesezeit

Einleitung

Eine Webseiten-Zeichen-App ist eine großartige Gelegenheit, um HTML, CSS und JavaScript zu üben und interaktive Tools zu erstellen. In diesem Artikel erstellen wir eine einfache Zeichen-App, die Werkzeuge zum Zeichnen verschiedener Formen, zum Auswählen von Farben und zum Speichern des erstellten Bildes enthält. Die Anwendung verfügt über eine benutzerfreundliche Oberfläche mit mehreren Werkzeugen, Pinselgrößen- und Farbeinstellungen.

Den vollständigen Quellcode und möglicherweise weitere Verbesserungen finden Sie auf unserer GitHub.

Demo-Projekt

Vorbereitung

Bevor wir mit dem Schreiben des Codes beginnen, stellen wir sicher, dass wir die erforderlichen Komponenten haben:

  • HTML — für die Seitenstruktur.

  • CSS — für die Gestaltung der Benutzeroberfläche.

  • JavaScript - zum Zeichnen, Bearbeiten von Ereignissen und Speichern von Bildern.

Wir benötigen auch Icons für die Schaltflächen, mit denen die Zeichenwerkzeuge ausgewählt werden. Diese Icons werden in unser Projekt über die Dateien im Ordner icons geladen.

HTML erstellen und Fotos und Dateien verknüpfen

Beginnen wir mit dem Erstellen einer HTML-Seite. Dies wird die Hauptstruktur unserer Anwendung sein.

HTML erstellt die Seitenstruktur und definiert das Markup für alle Elemente, die in der Anwendung angezeigt werden. Hier ist eine detailliertere Beschreibung der einzelnen Elemente im HTML-Code:

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Приложение для рисования</title>
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="script.js" defer></script>
  </head>
  <body>
    <div class="container">
      <!-- Панель инструментов -->
      <section class="tools-board">
        <div class="row">
          <label class="title">Формы</label>
          <ul class="options">
            <!-- Инструмент для рисования прямоугольника -->
            <li class="option tool" id="rectangle">
              <img src="icons/rectangle.svg" alt="Rectangle">
              <span>Прямоугольник</span>
            </li>
            <!-- Инструмент для рисования круга -->
            <li class="option tool" id="circle">
              <img src="icons/circle.svg" alt="Circle">
              <span>Круг</span>
            </li>
            <!-- Инструмент для рисования треугольника -->
            <li class="option tool" id="triangle">
              <img src="icons/triangle.svg" alt="Triangle">
              <span>Треугольник</span>
            </li>
            <li class="option">
              <input type="checkbox" id="fill-color">
              <label for="fill-color">Цвет заливки</label>
            </li>
          </ul>
        </div>
        <div class="row">
          <label class="title">Опции</label>
          <ul class="options">
            <!-- Инструмент кисть -->
            <li class="option active tool" id="brush">
              <img src="icons/brush.svg" alt="Brush">
              <span>Щетка</span>
            </li>
            <!-- Инструмент ластик -->
            <li class="option tool" id="eraser">
              <img src="icons/eraser.svg" alt="Eraser">
              <span>Ластик</span>
            </li>
            <!-- Ползунок для изменения размера кисти -->
            <li class="option">
              <input type="range" id="size-slider" min="1" max="30" value="5">
            </li>
          </ul>
        </div>
        <div class="row colors">
          <label class="title">Цвета</label>
          <ul class="options">
            <!-- Кнопки выбора цвета -->
            <li class="option"></li>
            <li class="option selected"></li>
            <li class="option"></li>
            <li class="option"></li>
            <li class="option">
              <input type="color" id="color-picker" value="#4A98F7">
            </li>
          </ul>
        </div>
        <div class="row buttons">
          <!-- Кнопки очистки и сохранения -->
          <button class="clear-canvas">Очистить</button>
          <button class="save-img">Сохранить как фото</button>
        </div>
      </section>

      <!-- Холст для рисования -->
      <section class="drawing-board">
        <canvas></canvas>
      </section>
    </div>
  </body>
</html>

HTML-Erklärung:

  1. <section class="tools-board">:

    • Dies ist eine Symbolleiste, die mehrere Optionen für den Benutzer enthält. Hier können Sie die Form (Rechteck, Kreis, Dreieck), Pinsel Farbe, Pinselgröße und andere Einstellungen auswählen.

  2. <ul class="options">:

    • Innerhalb der Symbolleiste werden Listen (<ul>) erstellt, die jeweils eine Gruppe von Optionen darstellen. Dies ist eine Liste von Schaltflächen zum Auswählen einer Form (Rechteck, Kreis usw.), Ändern der Farbe, der Pinselgröße und anderer Einstellungen.

  3. <canvas>:

    • Dies ist die Hauptleinwand, auf der gezeichnet wird. Sie enthält keinen Standardinhalt und verwendet JavaScript zum Zeichnen.

  4. Schaltflächen und Schieberegler:

    • Mit den Schaltflächen "Löschen" und "Als Foto speichern" können Sie die Leinwand löschen bzw. das Bild speichern. Mit dem Schieberegler (<input type="range">) können Sie die Größe des Pinsels ändern.

  5. Farbige Schaltflächen:

    • Im Farbbereich gibt es mehrere Schaltflächen, um die Farbe des Pinsels auszuwählen. Jede Schaltfläche repräsentiert eine Farbe und das letzte Element ist ein Element zum Auswählen einer Farbe mit einem Standardfarbwähler.

Styling

Nachdem die HTML-Struktur fertig ist, können wir mit dem Styling mit CSS fortfahren. Hier ist ein Beispiel für Stile für unsere Anwendung:

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap');

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: #040925;
}

.container {
  display: flex;
  width: 100%;
  gap: 10px;
  padding: 10px;
  max-width: 1050px;
}

section {
  background: #fff;
  border-radius: 7px;
}

.tools-board {
  width: 210px;
  padding: 15px 22px 0;
}

.tools-board .row {
  margin-bottom: 20px;
}

.row .options {
  list-style: none;
  margin: 10px 0 0 5px;
}

.row .options .option {
  display: flex;
  cursor: pointer;
  align-items: center;
  margin-bottom: 10px;
}

.option:is(:hover, .active) img {
  filter: invert(17%) sepia(90%) saturate(3000%) hue-rotate(900deg) brightness(100%) contrast(100%);
}

.option :where(span, label) {
  color: #5A6168;
  cursor: pointer;
  padding-left: 10px;
}

.option:is(:hover, .active) :where(span, label) {
  color: #4A98F7;
}

.option #fill-color {
  cursor: pointer;
  height: 14px;
  width: 14px;
}

#fill-color:checked ~ label {
  color: #4A98F7;
}

.option #size-slider {
  width: 100%;
  height: 5px;
  margin-top: 10px;
}

.colors .options {
  display: flex;
  justify-content: space-between;
}

.colors .option {
  height: 20px;
  width: 20px;
  border-radius: 50%;
  margin-top: 3px;
  position: relative;
}

.colors .option:nth-child(1) {
  background-color: #fff;
  border: 1px solid #bfbfbf;
}

.colors .option:nth-child(2) {
  background-color: #000;
}

.colors .option:nth-child(3) {
  background-color: #E02020;
}

.colors .option:nth-child(4) {
  background-color: #6DD400;
}

.colors .option:nth-child(5) {
  background-color: #4A98F7;
}

.colors .option.selected::before {
  position: absolute;
  content: "";
  top: 50%;
  left: 50%;
  height: 12px;
  width: 12px;
  background: inherit;
  border-radius: inherit;
  border: 2px solid #fff;
  transform: translate(-50%, -50%);
}

.colors .option:first-child.selected::before {
  border-color: #ccc;
}

.option #color-picker {
  opacity: 0;
  cursor: pointer;
}

.buttons button {
  width: 100%;
  color: #fff;
  border: none;
  outline: none;
  padding: 11px 0;
  font-size: 0.9rem;
  margin-bottom: 13px;
  background: none;
  border-radius: 4px;
  cursor: pointer;
}

.buttons .clear-canvas {
  color: #6C757D;
  border: 1px solid #6C757D;
  transition: all 0.3s ease;
}

.clear-canvas:hover {
  color: #fff;
  background: #6C757D;
}

.buttons .save-img {
  background: #4A98F7;
  border: 1px solid #4A98F7;
}

.drawing-board {
  flex: 1;
  overflow: hidden;
}

.drawing-board canvas {
  width: 100%;
  height: 100%;
}

Dieses CSS formatiert Elemente wie Schaltflächen, Farben und Größen und schafft so eine moderne und benutzerfreundliche Oberfläche.

Schreiben von Logik in JavaScript

Kommen wir nun zum interessantesten Teil - der Zeichenfunktionalität. Wir verwenden JavaScript, um Ereignisse zu verarbeiten, die mit dem Zeichnen auf der Leinwand zusammenhängen. Der JavaScript-Code wird über die Datei script.js eingebunden, die wir uns im Folgenden ansehen werden:

Der JavaScript-Code steuert die Zeichenfunktionalität auf der Leinwand, interagiert mit dem Benutzer und aktualisiert die Anzeige basierend auf den ausgewählten Einstellungen. Schauen wir uns die Details jedes Code-Schnipsels an.

Initialisierung von Variablen:

const canvas = document.querySelector("canvas"),
    toolBtns = document.querySelectorAll(".tool"),
    fillColor = document.querySelector("#fill-color"),
    sizeSlider = document.querySelector("#size-slider"),
    colorBtns = document.querySelectorAll(".colors .option"),
    colorPicker = document.querySelector("#color-picker"),
    clearCanvas = document.querySelector(".clear-canvas"),
    saveImg = document.querySelector(".save-img"),
    ctx = canvas.getContext("2d");

let prevMouseX, prevMouseY, snapshot,
    isDrawing = false,
    selectedTool = "brush",
    brushWidth = 5,
    selectedColor = "#000";
  • canvas: Verweist auf das Element <canvas> auf der Seite, auf der gezeichnet wird.

  • toolBtns: Liste aller Werkzeugschaltflächen (Pinsel, Radiergummi und Formen), mit denen der Benutzer interagieren kann.

  • fillColor: Variable zum Verfolgen des Status des Kontrollkästchens "Füllfarbe".

  • sizeSlider: Link zum Schieberegler zur Auswahl der Pinselgröße.

  • colorBtns: Variable für alle Farbauswahlschaltflächen, auf die der Benutzer klicken kann, um eine Farbe auszuwählen.

  • colorPicker: Link zum Standard-HTML-Farbwähler.

  • clearCanvas und saveImg: Schaltflächen zum Löschen der Leinwand und zum Speichern des Bildes.

  • ctx: Der Kontext des Canvas, mit dem Linien, Formen und andere Operationen gezeichnet werden.

Einstellung des Canvas-Hintergrunds:

const setCanvasBackground = () => {
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = selectedColor;
}

Dieser Code legt einen weißen Hintergrund für die Leinwand fest und stellt dann die aktuelle Farbe des Pinsels zum Zeichnen wieder her.

Initialisierung der Leinwand nach dem Laden der Seite:

window.addEventListener("load", () => {
    canvas.width = canvas.offsetWidth;
    canvas.height = canvas.offsetHeight;
    setCanvasBackground();
});

Beim Laden der Seite wird die Größe der Leinwand entsprechend ihrer aktuellen Größe auf dem Bildschirm festgelegt (über offsetWidth und offsetHeight). Dann wird die Funktion zum Einstellen des Hintergrunds aufgerufen.

Ereignishandler:

  1. Werkzeugauswahl-Handler (Pinsel, Radiergummi und Formen):

toolBtns.forEach(btn => {
    btn.addEventListener("click", () => {
        document.querySelector(".options .active").classList.remove("active");
        btn.classList.add("active");
        selectedTool = btn.id;
    });
});

Jede Schaltfläche des Tools (toolBtns) fügt einen Klickereignishandler hinzu, der die Schaltfläche aktiviert, indem er die Klasse active hinzufügt und das ausgewählte Tool ändert, indem er die Variable selectedTool aktualisiert.

  1. Größe des Pinsels ändern:

sizeSlider.addEventListener("change", () => brushWidth = sizeSlider.value);

Wenn der Benutzer den Wert des Schiebereglers ändert, wird die Größe des Pinsels aktualisiert.

  1. Farbwechsel:

colorBtns.forEach(btn => {
    btn.addEventListener("click", () => {
        document.querySelector(".options .selected").classList.remove("selected");
        btn.classList.add("selected");
        selectedColor = window.getComputedStyle(btn).getPropertyValue("background-color");
    });
});

Jede Farbauswahltaste aktualisiert die aktuelle Pinsel Farbe (selectedColor) und aktiviert die ausgewählte Schaltfläche durch Hinzufügen der Klasse selected.

  1. Verwendung der Farbauswahl:

colorPicker.addEventListener("change", () => {
    colorPicker.parentElement.style.background = colorPicker.value;
    colorPicker.parentElement.click();
});

Wenn der Benutzer eine Farbe über den Standard-HTML-Picker auswählt, wird die Farbe auch auf der Schaltfläche aktualisiert.

  1. Leinwand reinigen:

clearCanvas.addEventListener("click", () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    setCanvasBackground();
});

Wenn Sie auf die Schaltfläche „Löschen“ klicken, wird die gesamte Leinwand gelöscht und der Hintergrund wiederhergestellt.

  1. Bild speichern:

saveImg.addEventListener("click", () => {
    const link = document.createElement("a");
    link.download = `${Date.now()}.jpg`;
    link.href = canvas.toDataURL();
    link.click();
});

Wenn Sie auf die Schaltfläche "Als Foto speichern" klicken, wird ein temporärer Link zum Herunterladen des Bildes erstellt, der den Inhalt der Leinwand in das Format data URL konvertiert.

Zeichnen auf Leinwand:

const startDraw = (e) => {
    isDrawing = true;
    prevMouseX = e.offsetX;
    prevMouseY = e.offsetY;
    ctx.beginPath();
    ctx.lineWidth = brushWidth;
    ctx.strokeStyle = selectedColor;
    ctx.fillStyle = selectedColor;
    snapshot = ctx.getImageData(0, 0, canvas.width, canvas.height);
}

const drawing = (e) => {
    if (!isDrawing) return;
    ctx.putImageData(snapshot, 0, 0);
    if (selectedTool === "brush" || selectedTool === "eraser") {
        ctx.strokeStyle = selectedTool === "eraser" ? "#fff" : selectedColor;
        ctx.lineTo(e.offsetX, e.offsetY);
        ctx.stroke();
    } else if (selectedTool === "rectangle") {
        drawRect(e);
    } else if (selectedTool === "circle") {
        drawCircle(e);
    } else {
        drawTriangle(e);
    }
}

canvas.addEventListener("mousedown", startDraw);
canvas.addEventListener("mousemove", drawing);
canvas.addEventListener("mouseup", () => isDrawing = false);
  • startDraw: Wenn der Benutzer auf die Leinwand klickt, beginnt das Zeichnen. Die Anfangskoordinaten werden gespeichert und ein Snapshot des aktuellen Zustands der Leinwand wird erstellt (zum Abbrechen).

  • drawing: Wenn der Benutzer die Maus bewegt, wird das Zeichnen entsprechend dem ausgewählten Werkzeug ausgeführt.

Im Allgemeinen erstellt HTML die Benutzeroberfläche und Struktur, während JavaScript alle Funktionen zum Zeichnen, Ändern von Werkzeugen und Speichern des Bildes verwaltet.

Ausgezeichnet. Und so sieht der gesamte Java-Skriptcode aus:

const canvas = document.querySelector("canvas"),
    toolBtns = document.querySelectorAll(".tool"),
    fillColor = document.querySelector("#fill-color"),
    sizeSlider = document.querySelector("#size-slider"),
    colorBtns = document.querySelectorAll(".colors .option"),
    colorPicker = document.querySelector("#color-picker"),
    clearCanvas = document.querySelector(".clear-canvas"),
    saveImg = document.querySelector(".save-img"),
    ctx = canvas.getContext("2d");

let prevMouseX, prevMouseY, snapshot,
    isDrawing = false,
    selectedTool = "brush",
    brushWidth = 5,
    selectedColor = "#000";

const setCanvasBackground = () => {
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = selectedColor;
}

window.addEventListener("load", () => {
    canvas.width = canvas.offsetWidth;
    canvas.height = canvas.offsetHeight;
    setCanvasBackground();
});

// Funktionen zum Zeichnen von Formen
const drawRect = (e) => {
    if (!fillColor.checked) {
        return ctx.strokeRect(e.offsetX, e.offsetY, prevMouseX - e.offsetX, prevMouseY - e.offsetY);
    }
    ctx.fillRect(e.offsetX, e.offsetY, prevMouseX - e.offsetX, prevMouseY - e.offsetY);
}

const drawCircle = (e) => {
    ctx.beginPath();
    let radius = Math.sqrt(Math.pow((prevMouseX - e.offsetX), 2) + Math.pow((prevMouseY - e.offsetY), 2));
    ctx.arc(prevMouseX, prevMouseY, radius, 0, 2 * Math.PI);
    fillColor.checked ? ctx.fill() : ctx.stroke();
}

const drawTriangle = (e) => {
    ctx.beginPath();
    ctx.moveTo(prevMouseX, prevMouseY);
    ctx.lineTo(e.offsetX, e.offsetY);
    ctx.lineTo(prevMouseX * 2 - e.offsetX, e.offsetY);
    ctx.closePath();
    fillColor.checked ? ctx.fill() : ctx.stroke();
}

// Werkzeugmaschinen
toolBtns.forEach(btn => {
    btn.addEventListener("click", () => {
        document.querySelector(".options .active").classList.remove("active");
        btn.classList.add("active");
        selectedTool = btn.id;
    });
});

// Pinselreiniger
sizeSlider.addEventListener("change", () => brushWidth = sizeSlider.value);

colorBtns.forEach(btn => {
    btn.addEventListener("click", () => {
        document.querySelector(".options .selected").classList.remove("selected");
        btn.classList.add("selected");
        selectedColor = window.getComputedStyle(btn).getPropertyValue("background-color");
    });
});

colorPicker.addEventListener("change", () => {
    colorPicker.parentElement.style.background = colorPicker.value;
    colorPicker.parentElement.click();
});

// Leinwand reinigen
clearCanvas.addEventListener("click", () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    setCanvasBackground();
});

// Bild speichern
saveImg.addEventListener("click", () => {
    const link = document.createElement("a");
    link.download = `${Date.now()}.jpg`;
    link.href = canvas.toDataURL();
    link.click();
});

// Zeichnen
const startDraw = (e) => {
    isDrawing = true;
    prevMouseX = e.offsetX;
    prevMouseY = e.offsetY;
    ctx.beginPath();
    ctx.lineWidth = brushWidth;
    ctx.strokeStyle = selectedColor;
    ctx.fillStyle = selectedColor;
    snapshot = ctx.getImageData(0, 0, canvas.width, canvas.height);
}

const drawing = (e) => {
    if (!isDrawing) return;
    ctx.putImageData(snapshot, 0, 0);
    if (selectedTool === "brush" || selectedTool === "eraser") {
        ctx.strokeStyle = selectedTool === "eraser" ? "#fff" : selectedColor;
        ctx.lineTo(e.offsetX, e.offsetY);
        ctx.stroke();
    } else if (selectedTool === "rectangle") {
        drawRect(e);
    } else if (selectedTool === "circle") {
        drawCircle(e);
    } else {
        drawTriangle(e);
    }
}

canvas.addEventListener("mousedown", startDraw);
canvas.addEventListener("mousemove", drawing);
canvas.addEventListener("mouseup", () => isDrawing = false);

Dieser Code implementiert:

  • Zeichnen verschiedener Figuren (Rechteck, Kreis, Dreieck).

  • Auswahl der Instrumente, einschließlich Pinsel, Radiergummi und Fülloptionen.

  • Farbe und Größe des Pinsels ändern.

  • Leinwand reinigen und Bild speichern.

Ergebnisse und Schlussfolgerung

Wir haben eine einfache Anwendung zum Zeichnen in HTML, CSS und JavaScript erstellt, mit der Sie verschiedene Formen zeichnen, die Farbe und Größe des Pinsels ändern und das Bild speichern können. Diese Anwendung kann durch Hinzufügen zusätzlicher Tools, Verbesserung der Benutzeroberfläche und Integration mit dem Server zum Speichern und Austauschen von Zeichnungen erweitert werden.

🎯Hör auf zu zögern

Artikel gefallen?
Zeit zum Üben!

Bei Kodik liest du nicht nur — du schreibst sofort Code. Theorie + Praxis = echte Skills.

Sofortige Praxis
🧠KI erklärt Code
🏆Zertifikat

Keine Registrierung • Keine Karte