みどりのあくま

勉強したことをアウトプットしていきます。

pixi.js+netliftyで画像ジェネレーターを作った

今年の3月ぐらいに「pavicon maker」というwebアプリを作りました。

pavicon.netlify.com

簡単にいうと画像加工アプリみたいな感じのものです。
ちょっとした、ファンアプリだと思ってもらえばいいです。

この記事ではその経緯とどう実装したのかを解説します。

何をするものなのか?

現在「けものフレンズ ぱびりおん」というゲームがリリースキャンペーンで、twitterのアイコンを期間限定で公開していました。
その後ファンアートでアイコン化されなかったフレンズのアイコンを作っている方がいて、それにインスパイアされてアイコンの中心のキャラ以外を作成するwebアプリを作ろうとしました。
キャラの作成はちょっと無理そうなので諦めました。
画力があればモンタージュ形式でキャラが作れるアプリでも作ろうかと考えていましたが、まあ無理ですよねw

ちなみに、ぱびりおんのアイコンということとfaviconという言葉があるので、それを文字って「pavicon」という名前にしました。

作成方法

アプリ部分

今回のアプリ作成で一番困難だったのは、どうやってアウトラインを作成するかでした。

画像処理ということでcanvasで加工して、UIは普通のhtmlなどの要素で構成しました。

モジュールハンドラー

今回はfuseboxを使いました。

github.com

ちょっと小耳の挟んでたので気になったので使ってみました。
個人的には中々使いやすくよかったです。
公式のドキュメントも十分ありますし、デフォルトでプラグインもいくつかあるので使う上ではあまり問題はありませんでした。
また、fuse.js にタスクを書けるのが非常に便利でした。
webpackより取っ付きやすかったです。
時間がある時にもう少し使ってみたいと思います。

カラーピッカー

カラーピッカーは jscolor というライブラリを使用しました。

jscolor - JavaScript Color Picker (Palette) with touch support

このライブラリの性質上、 head で読み込む必要があるので、npm で管理せずに head で読み込ませています。
本当はひとまとめに出来ればいいのですが、自分の理想となる動きが出来るものがこれしか見つからなかったので…
また、コード内でカラーコードとrgbのパラメーターに変換するのに tinycolor2 というライブラリを使いました。

www.npmjs.com

canvas

画像加工部分に canvas を使いました。
ライブラリは pixi.js を使いました。

www.pixijs.com

pixi.js を使たのはアウトラインを描画できるて、実装が楽なのが調べた中では pixi.js しかなかったからです。
他のライブラリだと実現できてもかなり処理が重くあまり実用的ではありませんでした。
アウトラインはデフォルトのフィルターがあるのでそれを使いました。
楽ちんです。

pixijs.io

アウトラインのフィルタ以外にも、色変えやドロップシャドウもフィルターを使っています。

pixijs.io

pixijs.io

フィルターを使って他にも色々なことが出来そうなので、時間があるときに触ってみようと思います。

CSS

cssフレームワークbootstrap を使っています。
cssのみ使う予定なので headbootstrapcssのみ読み込んでいます。

出来るだけ bootstrap のものそのままを使ったのですが、input type="range"はbootstrap性のものがなかったので下記記事を参考にして自作しました。
ちなみに参考にしたのはline風にやつです。

qiita.com

画像のアップロード

画像はアップロードした画像を Image クラスとして読み込んで、それを pixi.jstexter として読み込んでいます。
コールバックが多くあまりすっきりした形ではないので、手直しして別の機会にそれに関して記事を別途書きたいと思います。
ちなみに読み込んだテクスチャはそのままだと、アウトラインを描画する面が足りなので、一度大きめの containeraddChild で追加して RenderTexture で余白が大き目のテクスチャとして書き出し、スプライトとして生成しなおしています。

  // アップロードした画像をtextureとして読み込みspriteに貼り付ける
  const texture = new PIXI.Texture(new PIXI.BaseTexture(image));
  const loadSprite = new PIXI.Sprite(texture);
  loadSprite.anchor.set(0.5);
  loadSprite.x = 325;
  loadSprite.y = 350;
  const r = loadSprite.width / loadSprite.height ;
  loadSprite.height = 600;
  loadSprite.width = 600 * r;

  // 読み込んだ画像のspriteをcontainerに入れる
  const container = new PIXI.Container();
  container.addChild(loadSprite);

  // render textureを使ってcontainerをtextureにする
  const rt = PIXI.RenderTexture.create(650, 650);
  app.renderer.render(container, rt);

  // containerのtextureを貼り付けたspriteを生成
  const largeSprite = PIXI.Sprite.from(rt);

画像のDL

下記の記事を参考に実装しました。

http:// https://st40.xyz/one-run/article/133/

一度キャンバスからbase64のデータ出力して、それをblobデータに変換、そのblobデータをダウンロード出来るURLを生成して、自分でイベント発火させダウンロードしています。
ちょっと回りくどいやり方ですが、他の方法もないみたいなのでこちらの方法で実装しました。

デプロイ部分

デプロイ先にはNetlifyを使用しました。

www.netlify.com

最近話題なのでご存知の方も多いと思います。 Netlifyは静的ファイルをホスティングするサービスです。
無料でもhttps対応、サブドメインをもらえます。
有料プランだと、カスタムドメインを設定できます。
また、デプロイも自動で行います。

github pagesだとパブリックにしないと使えませんでしたが、Netlifyだとプライベートリポジトリで使えます。
また、github pagesだと手動でビルドしてpushするか、何かしらのサービスを別に使ってビルドする必要があります。
しかし、NetlifyだとNetlify側でビルドしてもらえるので、色々と楽です。

自分は完全に気にって、最近はNetlifyばかり使っています。

まとめ

アウトラインをどうするかで色々なライブラリを探していましたがどれもいまいちで、トライアンドエラーを繰り返し1ヶ月くらいかかってしまったと思います。
次回からはもっと事前に調査して、素早く実装出来るようにして行きたいと思います。
また、pixi.js の実装が重いらしく、スマホだとかなりカクカクとした動きになってしまいます。
時間があれば pixi.js をもっと調べてここら辺より最適化ができないか調査したいと思います。