BLOG ブログ


2024.05.09

意外と簡単な画像生成~canvasを使ってみる~

時折、ブラウザ上で画像生成を行っているサイトを見かけます。

例)ロゴジェネレータ


このサイトでは、文字入力によってリアルタイムに画像が生成されます。入力された文字をサーバに送っている様子はありません。一体どうやって画像生成を行っているのでしょうか。

ここで使われているのが「canvas」です。今回はcanvasでの簡単な描画を行い、それをPNGとして書き出す方法を見ていきます。

canvasとは?

canvasとはHTML要素のひとつであり、まさしく絵を描くためのキャンバスのようなものです。JavaScriptを記述することにより、canvas上で自由に描画を行うことがでます。例えばグラフ、イラストの描画、写真の編集、アニメーションなど。もちろん2Dだけではなく、3Dを扱うこともできます。WebGLも利用できるため、かなり複雑な3Dアニメーションを描画することも可能です(とても難しいけど!)

canvas要素を使うにあたり、まずHTML側でやることは、widthとheightの値を決めることです。JSからsetAttributeで指定しても大丈夫です。ただしCSSによるwidthとheightの指定は意味合いが異なり、単に(画像を拡縮するように)領域を拡大縮小するだけになります。

例を作成してみました。

ボタンを押下した際、上に表示されているのがcanvas、下に表示されているのが生成されたPNG画像です。
「画像生成」を押すたびに、つまりVueの変数の値が変わるたびに、canvasに併せて下の画像も変化するのが分かります。
コードについてはVueを使用して書いています。

<canvas id="testCvs" width="300" height="300"></canvas>

なお、例で挙げたロゴジェネレータのHTMLソースにはcanvasが出てきません。どういうことかというと、結果の画像だけが欲しいなら、canvasは必ずしも画面に表示する必要はないのです。index.js内を「createElement」で検索すると、canvas要素を生成している行が見つかります。この見えないcanvas上で画像生成を行っているのです。

こうして確保した領域から、JSでコンテキストを取得、描画を行います。コンテキストの取得とはざっくり言えば、この領域を2Dとして扱うためのインタフェースを取得することです。

const cvs = document.getElementById('testCvs')
const context = cvs.getContext('2d')

JSでは、文字列、矩形、多角形、パスを用いた直線や曲線などを描画することができます。
今回は詳しく取り扱いませんが、mdnに詳細が載っています。これらを組み合わせて複雑な描画を行うこともできます。

キャンバスでの図形の描画 - Web API | MDN

基本的に、描画は「色を指定する→形と塗り方を指定する」、或いは「色を指定する→パスを指定する→塗り方を指定する」の形で行います。

図形を描いてみる

今回は、背景を白で塗りつぶし、ランダムな位置に赤と青の正方形を描いてみます。
まず、背景の塗りつぶしはこのようになります。

context.fillStyle = '#fff'
context.fillRect(0, 0, 300, 300)

今回はキャンバスサイズを300x300にしたので、画面いっぱいに白い矩形を描画しました。fillRectの引数はそれぞれ(始点のX座標、始点のY座標、横幅、高さ)です。
さきほど述べたように、まず塗りつぶしの色を指定してから、四角形に塗りつぶしを行っています。

次に、ランダムな座標をふたつ決定し、それらを始点としてふたつの正方形を描いてみます。

// ランダムな位置に2つの四角形(50x50)
const point1X = Math.floor(Math.random() * (imgWidth - 50))
const point1Y = Math.floor(Math.random() * (imgHeight - 50))
const point2X = Math.floor(Math.random() * (imgWidth - 50))
const point2Y = Math.floor(Math.random() * (imgHeight - 50))
    
context.fillStyle = "rgb(200, 0, 0)"
context.fillRect(point1X, point1Y, 50, 50)
context.fillStyle = "rgba(0, 0, 200, 0.5)"
context.fillRect(point2X, point2Y, 50, 50)

やっていることは先ほどと一緒です。そしてこの通り、色指定には16進数だけではなく、rgbやrgbaを使用することもできます。

画像として出力する

では最後に、canvasに描画した内容をPNG形式で書き出してみます。やり方は非常にシンプルです。

displayImg.value = cvs.toDataURL()

左辺については、Vueで書いているためこの形式になっています。

右辺の通り、「toDataURL()」を実行することで、base64形式のコードが返ってきます。特に指定しない場合は、「image/png」として出力されます。

なので、この値をimg要素のsrc属性にセットすれば、画像が表示されます。

<img :src="displayImg" alt="生成した画像">

このように、canvasに描画した内容を画像にするのは意外と簡単です。今回は矩形を用いましたが、テキストの変更をリアルタイムに検知して、画像を変化させることももちろん可能です。ぜひ手元でもやってみてくださいね!


Kakko
ライター名:Kakko
草を育て、魚を愛で、本を読み、刺繍をするフロントエンドエンジニア。

主な記事一覧へ

一覧に戻る


LATEST ARTICLE 最新の記事

CATEGORY カテゴリー