はじめに
ウェブページ上のドローイングアプリケーションは、HTML、CSS、JavaScriptを練習し、インタラクティブなツールを作成する絶好の機会です。この記事では、さまざまな図形を描画し、色を選択し、作成した画像を保存するためのツールを含むシンプルな描画アプリケーションを作成します。アプリケーションには、複数のツール、ブラシサイズ設定、色を備えた便利なインターフェースがあります。
完全なソースコードと追加の改善については、 GitHub.

準備
コードを書き始める前に、必要なコンポーネントがあることを確認します。
HTML — ページ構造用。
CSS — インターフェースのスタイルを設定します。
JavaScript - 図面機能、イベント処理、および画像保存用。
また、描画ツールを選択するために使用するボタンのアイコンも必要です。これらのアイコンは、iconsフォルダー内のファイルを介してプロジェクトにアップロードされます。
HTMLの作成と写真やファイルの接続
まずはHTMLページの作成から始めましょう。これはアプリケーションの基本構造になります。
HTMLはページの構造を作成し、アプリケーションに表示されるすべての要素のマークアップを設定します。HTMLコードの各要素の詳細な説明は次のとおりです。
<!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の説明:
<section class="tools-board">:これは、ユーザーが選択できるオプションがいくつかあるツールバーです。ここでは、形状(長方形、円形、三角形)、ブラシの色、ブラシのサイズ、その他の設定を選択できます。
<ul class="options">:ツールバー内にはリスト(
<ul>)が作成され、それぞれがオプションのグループを表します。これは、形状(長方形、円など)を選択したり、色やブラシのサイズ、その他の設定を変更したりするためのボタンのリストです。
<canvas>:これは、描画が行われるメインのキャンバスです。デフォルトのコンテンツは含まれておらず、描画にはJavaScriptが使用されます。
ボタンとスライダー:
[クリア]ボタンと[写真として保存]ボタンを使用すると、キャンバスをクリアして画像を保存できます。スライダー(
<input type="range">)を使用すると、ブラシのサイズを変更できます。
カラーボタン:
色のセクションには、ブラシの色を選択するためのボタンがいくつかあります。各ボタンは色を表し、最後の要素は標準のカラーピッカーを使用して色を選択するための要素です。
スタイル
HTML構造の準備ができたので、CSSを使用してスタイルを設定できます。アプリケーションのスタイルの例を次に示します。
@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%;
}
このCSSは、ツールボタン、色、サイズなどの要素をデザインし、モダンで使いやすいインターフェースを作成します。
JavaScriptでのロジックの記述
それでは、最も興味深い部分である描画機能に移りましょう。キャンバス上の描画に関連するイベントを処理するために JavaScript を使用します。JavaScriptコードは、以下で説明するファイルscript.jsを介して接続されます。
JavaScriptコードは、キャンバス上の描画機能を制御し、ユーザーと対話し、選択した設定に応じて表示を更新します。各コードスニペットの詳細を検討しましょう。
変数の初期化:
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: 描画が行われるページの<canvas>要素を参照します。toolBtns: ユーザーが操作できるすべてのツールボタン(ブラシ、消しゴム、図形)のリスト。fillColor:「塗りつぶしの色」チェックボックスの状態を追跡するための変数。sizeSlider:ブラシサイズを選択するためのスライダーへのリンク。colorBtns:ユーザーが色を選択するためにクリックできるすべての色選択ボタンの変数。colorPicker:標準のHTMLカラーピッカーへのリンク。clearCanvasとsaveImg:キャンバスをクリアして画像を保存するためのボタン。ctx: 線や図形を描画したり、その他の操作を実行したりするためのキャンバス描画コンテキスト。
キャンバスの背景を設定するには:
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();
});ページが読み込まれると、キャンバスのサイズは画面上の現在のサイズに対応するように設定されます(offsetWidthおよびoffsetHeightを介して)。次に、背景を設定する関数が呼び出されます。
イベントハンドラ:
ツール選択ハンドラ(ブラシ、消しゴム、図形):
toolBtns.forEach(btn => {
btn.addEventListener("click", () => {
document.querySelector(".options .active").classList.remove("active");
btn.classList.add("active");
selectedTool = btn.id;
});
});ツールの各ボタン(toolBtns)は、activeクラスを追加してボタンをアクティブにし、selectedTool変数を更新して選択したツールを変更するクリックイベントハンドラを追加します。
ブラシサイズの変更:
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");
});
});各色選択ボタンは、現在のブラシの色を更新し (selectedColor)、選択したボタンをアクティブにして、クラスを追加します selected。
カラーピッカーの使用:
colorPicker.addEventListener("change", () => {
colorPicker.parentElement.style.background = colorPicker.value;
colorPicker.parentElement.click();
});ユーザーが標準のHTMLピッカーを介して色を選択すると、ボタンの色も更新されます。
キャンバスのクリア:
clearCanvas.addEventListener("click", () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
setCanvasBackground();
});
[クリア]ボタンをクリックすると、キャンバス全体がクリアされ、背景が復元されます。
画像を保存しています:
saveImg.addEventListener("click", () => {
const link = document.createElement("a");
link.download = `${Date.now()}.jpg`;
link.href = canvas.toDataURL();
link.click();
});[写真として保存]ボタンをクリックすると、キャンバスのコンテンツをdata URL形式に変換して、画像をダウンロードするための一時リンクが作成されます。
キャンバスに描画:
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: ユーザーがキャンバスをクリックすると、描画が開始されます。初期座標が保存され、キャンバスの現在の状態のスナップショットが作成されます(キャンセル用)。drawing: ユーザーがマウスを動かすと、選択したツールに応じて描画が実行されます。
一般的に、HTMLはインターフェースと構造を作成し、JavaScriptはすべての描画機能、ツールの変更、および図面の保存を管理します。
素晴らしい。これがすべてのJavaスクリプトコードの外観です。
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();
});
// 図形を描くための関数
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();
}
// ツールハンドラ
toolBtns.forEach(btn => {
btn.addEventListener("click", () => {
document.querySelector(".options .active").classList.remove("active");
btn.classList.add("active");
selectedTool = btn.id;
});
});
// ブラシハンドラー
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();
});
// キャンバスをクリアする
clearCanvas.addEventListener("click", () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
setCanvasBackground();
});
// 画像を保存しています
saveImg.addEventListener("click", () => {
const link = document.createElement("a");
link.download = `${Date.now()}.jpg`;
link.href = canvas.toDataURL();
link.click();
});
// 描画
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);
このコードは以下を実装します。
さまざまな図形を描く (長方形、円形、三角形)。
ツールの選択ブラシ、消しゴム、塗りつぶしオプションを含みます。
ブラシの色とサイズを変更する.
キャンバスをクリアして画像を保存する.
結論とまとめ
HTML、CSS、JavaScriptでさまざまな図形を描画し、ブラシの色とサイズを変更し、画像を保存できるシンプルな描画アプリケーションを作成しました。このアプリケーションは、追加のツールの追加、インターフェースの改善、および図面の保存と共有のためのサーバーとの統合によって拡張できます。
