JavaScript - お絵描きアプリの作り方【機能追加編】

今回は、【基本編】で作ったシンプルなお絵描きアプリに機能を追加します。線の太さをスライダーで変更したり、色をカラーピッカーから選択できるようにして、より楽しく遊べるアプリを作ってみましょう。

JavaScript - お絵描きアプリの作り方【機能追加編】
Photo by Markus Spiske / Unsplash

線の太さと色を選べるお絵描きアプリ

マウスやタッチパッドなどのポインティングデバイスでキャンバスに自由に描画できるお絵描きアプリを JavaScript で作ります。【基本編】に引き続き、今回は【機能追加編】です。

【基本編】では、線の太さと色は特に指定しなかったので、描画される線のスタイルはデフォルトの 1px 黒でした。今回は、線の太さと色を自由に選べるようにコードを追加していきます。

お絵描きアプリの基本的な作り方については、以下の記事からご覧ください。

JavaScript - お絵描きアプリの作り方【基本編】
HTML のキャンバス <canvas> と JavaScript でシンプルなお絵描きアプリを作ります。線の描画機能と消去ボタンのみの最低限のコードで、自由に描画するための基本的な方法を学びましょう。

サンプルプロジェクト

最初に、今回作成するお絵描きアプリの動きを確認しておきましょう。

  • キャンバス内でマウスボタン(タッチパッドなど)を押しながら動かして、描画する
  • スライダーを動かして、線の太さを選ぶ
  • カラーピッカーで、線の色を選ぶ
お絵描きアプリのサンプル(Safariブラウザのカラーピッカー)
お絵描きアプリのサンプル(Safariブラウザのカラーピッカー)

HTML

まずは HTML です。ここでは、必要最低限の要素のみを掲載します。より詳しく知りたい場合は、記事の最後にある CodePen のコードを参考にしてください。

【基本編】で作成したキャンバス <canvas> と消去ボタン <button> の他に、今回は次の要素を追加します。

  1. 線の太さの表示欄 <p>
  2. 線の太さを決めるスライダー <input type="range">
  3. 線の色を決めるカラーピッカー <input type="color">

1. 線の太さの表示欄

  • 描画する線の太さを表示するエリア <p> を用意します。
  • 最初の線の太さは 3 としておきます。
<!-- 線の太さの表示欄 -->
<p id="width-display">3</p>

2. 線の太さを決めるスライダー

  • <input> 要素に type="range" を指定すると、スライダーを作成することができます。
  • 最小値を min="1"、最大値を max="30" にして、1から 30 までで線の太さを選べるようにします。
  • 初期値を value="3" とし、最初のスライダーの値(線の太さ)を 3 に設定します。
<!-- 線の太さを決めるスライダー -->
<input type="range" id="slider" min="1" step="1" max="30" value="3"><br>
<label for="slider">線の太さ</label>

3. 線の色を決めるカラーピッカー

  • <input> 要素に type="color" を指定すると、カラーピッカーを作成することができます。カラーピッカーの見た目は、ブラウザによって異なります。この記事に掲載しているGIF画像サンプルは、Safariブラウザのカラーピッカーです。
  • 初期値を value="#777777" とし、最初の色を灰色に設定します。
<!-- 線の色を決めるカラーピッカー -->
<input type="color" id="color-picker" value="#777777"><br>
<label for="color-picker">線の色</label>

以上で、【基本編】で作成したキャンバスと消去ボタンに加えて、線の太さの表示欄、スライダー、カラーピッカーを追加できました。

<canvas id="drawing-area" width="500" height="400"></canvas>

<!-- 線の太さの表示欄 -->
<p id="width-display">3</p>

<!--線の太さを決めるスライダー-->
<input type="range" id="slider" min="1" step="1" max="30" value="3"><br>
<label for="slider">線の太さ</label>

<!-- 線の色を決めるカラーピッカー -->
<input type="color" id="color-picker" value="#777777"><br>
<label for="color-picker">線の色</label>

<button id="clear-button">Clear</button>

JavaScript

続いて JavaScript です。ユーザーが変更したスライダーの値とカラーピッカーの色を JavaScript で取得して、描画スタイルに反映させるようにコーディングします。【基本編】で作成したコードに追加する形で解説していきますね。

要素を取得する

先ほど追加した要素を querySelector() メソッドで取得し、それぞれ変数に格納します。

const canvas = document.querySelector('#drawing-area');
const ctx = canvas.getContext('2d');
const clearBtn = document.querySelector('#clear-button');

// 線の太さの表示欄
const widthDisplay = document.querySelector('#width-display');
// 線の太さを決めるスライダー
const slider = document.querySelector('#slider');
// 線の色を決めるカラーピッカー
const colorPicker = document.querySelector('#color-picker');

変数を宣言する

線の「太さ」と「色」を格納するための変数を追加しましょう。

  • 線の太さ width は、スライダーの値 slider.value で初期化します。スライダーの初期値は value="3" としたので、最初の線の太さは 3 となります。
  • 線の色 color は、カラーピッカーの値 colorPicker.value で初期化します。カラーピッカーの初期値は value="#777777" としたので、最初は灰色になります。
let x;
let y;
let mousePressed = false;

// 線の太さ
let width = slider.value;
// 線の色
let color = colorPicker.value;

スライダーを動かして線の太さを変更する

スライダーで線の太さを変更するためのコードを書いていきましょう。

  • スライダーを動かしたときに発生するのは、input イベントです。addEventListener() メソッドでスライダーに input イベントを追加し、線の太さを変更します。
  • 線の太さ width に、スライダーの値 slider.value を代入します。
  • 線の太さの表示を、スライダーの値 slider.value にします。
// スライダーにinputイベントを追加
slider.addEventListener('input', function() {

  // 線の太さをスライダーの値にする
  width = slider.value;

  // 太さの表示をスライダーの値にする
  widthDisplay.textContent = slider.value;

});

スライダーを左右に動かして input イベントが発生するたびに、線の太さ width と線の太さの表示欄 widthDisplay を変更するコードができました。

this キーワードで書き換えてみよう

上の文は、this キーワードを使って下のように書くこともできますよ。

slider.addEventListener('input', function() {
  width = this.value;
  widthDisplay.textContent = this.value;
});

イベントハンドラー内で使われる this は、そのイベントが発生した要素(この場合は slider)を参照するので、slider.valuethis.value で表すことができます。

カラーピッカーで選択して線の色を変更する

次は、カラーピッカーで線の色を変更する文です。こちらも、カラーピッカーの値を取得する際に this キーワードを使って書いてみましょう。

  • 色を選択したときに発生するのは、input イベントです。カラーピッカーに input イベントを追加して、線の色を変更します。
  • 線の色 color に、カラーピッカーの値 this.valuecolorPicker.value)を代入します。
// カラーピッカーにinputイベントを追加
colorPicker.addEventListener('input', function() {

  // 線の色をカラーピッカーの値にする
  color = this.value;

});

描画する線のスタイルを指定する

スライダーで線の太さを、カラーピッカーで線の色を変更できるようになったら、その値を使って描画されるようにしましょう。線を描画するときに呼び出されるのは、関数 draw です。この関数にコードを追加していきますよ。

  • lineWidth プロパティで、線の太さを変数 width とします。
  • strokeStyle プロパティで、線の色を変数 color とします。
function draw(e) {
  if (!mousePressed) return;

  x2 = e.offsetX;
  y2 = e.offsetY;
  
  // 線の太さを指定
  ctx.lineWidth = width;
  // 線の色を指定
  ctx.strokeStyle = color;

  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(x2, y2);
  ctx.stroke();

  x = x2;
  y = y2;
}

線の太さや色などの描画スタイルについては、以下の記事を参考にしてください。

JavaScript - 図形に色やグラデーションを設定する方法
JavaScript で描画する図形にスタイルを設定するためのプロパティや、グラデーションカラーを作成するメソッドを紹介します。レインボーカラーや図形を立体的に見せるためのサンプルコードも掲載しているので参考にしてください。

線の太さと色を選んで描画できるようになったので、試しに描いてみると… 特に太い線では、線が切れているように見えてしまっていますね。これは、線の端の形が影響しているのが原因です。

線の端の形を設定していない場合の描画例
線の端の形を設定していない場合の描画例

線の端の形を指定する

stroke() メソッドで描画する線は、端の形を指定することができます。デフォルトでは、線の端は平らな形となっているので、連続して線を描画すると切れたような見た目になってしまいました。これを解決するためには、線の端を丸い形にするといいですよ。線の太さと色に続いて、関数 draw に文を追加しましょう。

  • lineCap プロパティで、線の端の形を round にします。
function draw(e) {
  if (!mousePressed) return;

  x2 = e.offsetX;
  y2 = e.offsetY;
  
  ctx.lineWidth = width;
  ctx.strokeStyle = color;

  // 線の端の形を指定
  ctx.lineCap = 'round';

  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(x2, y2);
  ctx.stroke();

  x = x2;
  y = y2;
}

完成コード

線の太さと色を選べる、お絵描きアプリのコードが完成です。

//*********************************************
// お絵描きアプリのコード 線の太さ・色選択機能付き
//*********************************************

const canvas = document.querySelector('#drawing-area');
const ctx = canvas.getContext('2d');
const clearBtn = document.querySelector('#clear-button');
// 線の太さの表示欄
const widthDisplay = document.querySelector('#width-display');
// 線の太さを決めるスライダー
const slider = document.querySelector('#slider');
// 線の色を決めるカラーピッカー
const colorPicker = document.querySelector('#color-picker');

let x;
let y;
let mousePressed = false;
// 線の太さ
let width = slider.value;
// 線の色
let color = colorPicker.value;

function startDrawing(e) {
  mousePressed = true;
  x = e.offsetX;
  y = e.offsetY;
}

function draw(e) {
  if (!mousePressed) return;
  x2 = e.offsetX;
  y2 = e.offsetY;
  
  // 線の太さを指定
  ctx.lineWidth = width;
  // 線の色を指定
  ctx.strokeStyle = color;
  // 線の端の形を指定
  ctx.lineCap = 'round';

  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(x2, y2);
  ctx.stroke();
  x = x2;
  y = y2;
}

// スライダーで線の太さを変更
slider.addEventListener('input', function() {
  width = this.value;
  widthDisplay.textContent = this.value;
});

// カラーピッカーで線の色を選択
colorPicker.addEventListener('input', function() {
  color = this.value;
});


canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
window.addEventListener("mouseup", () => mousePressed = false);
clearBtn.addEventListener('click', () => {
  ctx.clearRect(0, 0, canvas.width, canvas.height)
});

See the Pen JavaScript - Drawing App by Pyxofy (@pyxofy) on CodePen.

「きょうからはじめるスクラッチプログラミング入門」

Pyxofy から Scratch の基本をまとめた電子書籍を出版しました。
Kindle・Apple Books からご購入ください。

詳細はこちら

まとめ

今回は、JavaScript で線の太さと色を選んで描画できるお絵描きアプリの作り方を紹介しました。

HTML の <input> 要素で作るスライダーの値とカラーピッカーの値を JavaScript で取得すると、簡単に線の太さや色を変更することができましたね。お絵描きアプリの基本的なコードは【基本編】で解説しているので、ぜひ併せてご覧ください。

最後まで読んでいただき、ありがとうございます。この記事をシェアしてくれると嬉しいです!

SNSで Pyxofy とつながりましょう! LinkedInThreadsMastodon X (Twitter) @pyxofyFacebook

関連記事

JavaScript - ボールが跳ね返るアニメーションの作り方
ボールが動き続けるアニメーションを JavaScript で作ります。requestAnimationFrame() メソッドの使い方や、キャンバスに図形を描画してアニメーションを作る基本的な方法を学びましょう。
CSS Art – How to Make a Game Character – Bowser (King Koopa)
Large golden horns, spiky turtle back and a fiery breath. Let’s make Super Mario’s famous nemesis in this article, step-by-step.
CSS Animation – Car Driving Infinite Scroll – Part 1
Infinite, auto-scrolling animations are amazing to look at and easy to create with CSS. Learn how in this multi-part, step-by-step article.
スクラッチプログラミング - スクラッチアートのつくりかた
「スクラッチアート」のようなおえかきプロジェクトを Scratch でつくってみましょう。拡張機能(かくちょうきのう)の「ペン」をつかって、くろい画面(がめん)にカラフルないろでえがく、かんたんなプログラムです。