簡易アイキャッチジェネレータを作った

ブログを更新する上でいちばん面倒な作業はなに? そう聞かれたら、筆者は迷わずアイキャッチ作成!と答える。この作業がブログ更新の障壁になっていると断言してもいい。

このブログではアイキャッチを作らないと決めている。ただ別ブログでは意地でも毎記事なにか作らなきゃいけなかった。最悪無地の背景に記事タイトルだけでもいいかな、でもそんなシンプルなもののために高性能の Canva を使うのもなあという気持ちにもなった。

だったらそういうツールが別にあったら便利じゃない?と思ったので、簡易アイキャッチジェネレータを作成した。

デモ

思いきって固定ページに公開することにした。それがこちら。

設定項目が多いと面倒くさくなってしまう性分なので、テキスト、背景色、文字色を指定するだけでアイキャッチが作成できる必要最小限の構成にしてある。

使い方は上記のページに書いてあるので、そちらを参照してください。

ソースコード

このジェネレータは HTML, CSS, JavaScript で構成されている。本記事公開時点でのソースコードを以下に示す。

HTML

<form class="eyecatch-generator">

  <canvas id="eyecatch-canvas" height="630" width="1200"></canvas>

  <label for="eyecatch-text">テキスト</label>
  <textarea id="eyecatch-text">【サンプル】
ここにテキストを入れてください</textarea>

  <label for="eyecatch-bgcolor">背景色</label>
  <input id="eyecatch-bgcolor" type="text" value="#f57c00"/>

  <label for="eyecatch-fcolor">文字色</label>
  <input id="eyecatch-fcolor" type="text" value="#ffffff"/>

  <button id="eyecatch-button" type="button">ダウンロード</button>

</form>

form 内にアイキャッチを描画する canvas を格納した。キャンバスサイズは横 1200px × 縦 630px。フォーム下部のボタンを押すと、これと同じサイズの画像がダウンロードできる。

CSS

.eyecatch-generator{
  display: block;
  margin: 2em auto;
  padding: 1em;
  line-height: 1;
  font-size: 16px;
  background: #fff;
  color: #333;
  border-radius: 3px;
}
.eyecatch-generator canvas{
  display: block;
  margin-bottom: 2em;
  padding: 0;
  width: 100%;
  max-width: 600px;
}
.eyecatch-generator label{
  display: block;
  margin-bottom: .5em;
}
.eyecatch-generator textarea,
.eyecatch-generator input{
  display: block;
  margin-bottom: 1em;
  padding: .5em;
  line-height: 1.4;
  background: #eee;
  color: #333;
  border: none;
  border-radius: 3px;
  outline: none;
  appearance: none;
}
.eyecatch-generator textarea{
  width: 100%;
  max-width: 480px;
  height: 80px;
}
.eyecatch-generator input{
  width: 160px;
}
.eyecatch-generator textarea:hover,
.eyecatch-generator input:hover,
.eyecatch-generator textarea:focus,
.eyecatch-generator input:focus{
  outline: 2px steelblue solid;
}
.eyecatch-generator button{
  display: inline-block;
  margin: 1em .5em 1em 0;
  padding: .75em;
  background: #333;
  color: #fff;
  border: none;
  border-radius: 3px;
  outline: none;
  appearance: none;
}
.eyecatch-generator button:hover,
.eyecatch-generator button:focus{
  background: steelblue;
}

当ブログに合わせたスタイルになっているため、このまま適用すると表示が崩れる場合があるので注意。

JavaScript

document.addEventListener('DOMContentLoaded', makeEyecatch)

function makeEyecatch(){

  // フォーム内の要素を取得
  const canvas = document.querySelector('#eyecatch-canvas');
  const txt = document.querySelector('#eyecatch-text');
  const bgc = document.querySelector('#eyecatch-bgcolor');
  const fc = document.querySelector('#eyecatch-fcolor');
  const btn = document.querySelector('#eyecatch-button');

  // コンテキスト、キャンバスの幅と高さ、フォントサイズ、行間を定義
  const ctx = canvas.getContext('2d');
  const width = canvas.width;
  const height = canvas.height;
  const fsize = 64;
  const lheight = 1.6;

  // デフォルトの背景色と文字色を取得
  let dbgc = bgc.defaultValue;
  let dfc = fc.defaultValue;

  // キャンバスを描画する関数を呼び出す
  makeCanvas();

  // テキスト入力欄の内容が変更されたら、キャンバスを描画する関数を呼び出す
  txt.addEventListener('input', makeCanvas)

  // 背景色選択欄の値が変更されたら、背景色を設定し、キャンバスを描画する関数を呼び出す
  bgc.addEventListener('input', () => {
    if(bgc.value == ''){
      dbgc = bgc.defaultValue;
    } else{
      dbgc = bgc.value;
    }
    makeCanvas()
  })

  // 文字色選択欄の値が変更されたら、文字色を設定し、キャンバスを描画する関数を呼び出す
  fc.addEventListener('input', () => {
    if(fc.value == ''){
      dfc = fc.defaultValue;
    } else{
      dfc = fc.value;
    }
    makeCanvas()
  })

  // ダウンロードボタンがクリックされたら、キャンバスを画像としてダウンロードする関数を呼び出す
  btn.addEventListener('click', makeImg)

  function makeCanvas(){
  
    // キャンバスをクリア
    ctx.clearRect(0, 0, width, height);

    // 背景色を設定
    ctx.fillStyle = dbgc;
    ctx.fillRect(0, 0, width, height);

    // テキストエリアの文字列を改行区切りで配列に格納
    const line = txt.value.split(/\n/);

    for(let i = 0; i < line.length; i++){

      // 文字の行間を計算
      const d = fsize * lheight;

      // 文字が左右上下中央寄せになるよう計算
      const x = width / 2;
      const y = height / 2 + (i - (1 / 2) * (line.length - 1)) * d;

      // 文字のスタイルを設定
      ctx.textBaseline = 'middle';
      ctx.textAlign = 'center';
      ctx.fillStyle = dfc;
      ctx.font = `${fsize}px bold sans-serif`;

      // 文字を描画
      ctx.fillText(line[i], x, y);

    }
  }

  function makeImg(){
  
    // ボタンを無効化
    btn.disabled = true;

    canvas.toBlob((blob) => {

      // ダウンロード用リンクを作成
      const a = document.createElement('a');
      const url = URL.createObjectURL(blob);
      a.href = url;
      a.download = 'eyecatch.png';

      // リンクを追加してダウンロードを実行
      document.body.appendChild(a);
      a.click();
      a.remove();

      // URLオブジェクトを破棄
      URL.revokeObjectURL(url);

      // ボタンを有効化
      btn.disabled = false;

    }, 'image/png')
  }
}

コード自体はほぼ自力で書いたが、コード内のコメントは今話題の ChatGPT に入れてもらったものをこっちで修正して載せた。ありがとう人工知能。

上記のコードで特に苦労したのが、以下のテキストの y 座標を求めるための式だ。

const y = height / 2 + (i - (1 / 2) * (line.length - 1)) * d;

テキストが複数行に渡るときの垂直方向の中央寄せの計算式の求め方がよくわからなくて、等差数列やら階差数列やらを調べまくった記憶がある。今同じ式導けって言われても無理だと思う。

あとがき

シンプルなアイキャッチジェネレータを作ったので、どうせならと公開してみた。

1 か月前くらいに作って放置していたツールなので、特に JavaScript の部分はなにをやっているのか忘れていた部分が多く、ChatGPT に解説してもらってようやく理解することができた。自分で書いたコードなのに笑

実用に耐えうるツールなのかは謎だけど、JavaScript で canvas を操作する方法や、そこから画像を生成する方法を学べて勉強になった。自分がめんどくさくならない程度に、ちょこちょこ設定項目を増やしていけたらと思う。

編集
ホーム