ポケモン画像でアスキーアート風に変換するwebアプリを作った


こんにちは、Yuiです。

引き続き週イチ発信をしていきます。
今週は先週作ったポケモンAA化APIを使ってwebアプリを作ったのでその件について書きます。

過去の週イチ発信は以下

構成

構成はいつもどおりのNuxt.js + tailwind CSSです。
一度テンプレを作ったらずっと使ってしまいますね。

デプロイはvercelで行ってます。

動的OGP部分はこちらの記事に書いてあるとおりで、アスキーアート化するAPI部分に関しては先週こちらに書いてます。

使い方

使い方は上記にアクセスして、

  • 画像を選択
  • 変換ボタンをクリック
  • 後は待つだけ

のお手軽構成です。
ログインも不要なので、ぜひ遊んで見て下さい!

一応多言語化していて、ユーザーのブラウザ言語が日本語のときは日本語で英語のときは英語で表示できるようにしています。

デザインは塗り絵ツクール絵画ツクールの使いまわしですが、微妙にこだわったこととして、ローディングアニメーションをモンスターボールにしてます。笑

このモンスターボールに関しては、Temani Afifさんのこの記事から、自由に使って良いと書かれてあるのでありがたく拝借しました。

画像の圧縮処理

今回APIの処理部分が非常に重くなってしまう関係で、フロント側で画像を圧縮して送ってます。
絵画ツクールでも同じ処理を加えています。
やはり画像処理系は送る前にできる限り軽量化して送らないと時間がかかってしまいますね。

処理内容としては以下です。

/**
 * Canvasの描画して画像をリサイズする
 * @param {object} image - Imageオブジェクト
 * @param {number} limitWidth - 最大横幅
 * @param {number} limitHeight - 最大縦幅
 * @returns {string} - base64
 */
export default async function resizeImage(image, limitWidth, limitHeight) {
  const aspect = image.width / image.height;
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  let canvasWidth;
  let canvasHeight;
  if (image.width > limitWidth || image.height > limitHeight) {
    // 規定サイズよりも画像が大きい場合
    if (aspect > 1) {
      // 横長画像の場合
      canvasWidth = limitWidth;
      canvasHeight = limitHeight * (image.height / image.width);
    } else {
      // 縦長画像の場合
      canvasWidth = limitWidth * (image.width / image.height);
      canvasHeight = limitHeight;
    }
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;
  } else {
    // 規定サイズ内の場合
    canvas.width = image.width;
    canvas.height = image.height;
    canvasWidth = image.width;
    canvasHeight = image.height;
  }
  ctx.drawImage(
    image,
    0,
    0,
    image.width,
    image.height,
    0,
    0,
    canvasWidth,
    canvasHeight
  );
  return canvas.toDataURL("image/jpeg", 0.85);
}

あとがき

今回はネタアプリということで、先週遊びで作ったAPIをwebアプリ化してみました。
うまく変換できなかったり、変換できても使い所がわからない画像にはなるとは思いますが、楽しんでもらえると嬉しいです!