FrontEnd

React Konvaで状態管理されたCanvasを描画してみた

投稿日:

はじめに

着せ替えメーカーが流行っているらしく、自分でも作ってみたくなったので、技術調査をしました。着せ替えメーカーとは、用意されたキャラクターのパーツ(顔・目・髪・口など)を組み合わせたり、位置を調整したりしてオリジナルのキャラクターを作ることのできるサービスです。
スマホでの利用も考えていたので、異なる画面サイズでも、同じ比率でパーツを描画したり、位置調整をするか、という点が技術課題でした。この点を調べていくうちに、Canvasであれば、描画領域をスケールさせることで、Canvas内部の座標系を維持したまま拡大・縮小できることが分かったので、今回はCanvasと、CanvasをReactで使いやすくするためのReact Konvaについて調査しました。

Canvasとは?

Canvasとは、Web上で2Dグラフィックスを描画するためのAPIです。一番簡単な例だと、このようにCanvasに描画することができます。

以下のように、緑色の図形が描画されます。

このように、CanvasのAPI自体はすぐに試すことができるのですが、命令型のAPIとなっているので、状態の変化に応じてCanvasの内容を操作するようなアプリケーションを操作する場合、複雑な処理になることが想像できると思います。
また、Reactを使ってアプリケーションを構築したいため、相性の良いライブラリを探してみたところ、react-konvaが便利そうだったので、試してみたいと思います。

React Konvaとは

まず、Konvaは、Canvasのラッパーライブラリです。Canvasの命令型APIをラップし、Konva独自の「レイヤー」オブジェクト上に、図形などを追加したり、イベントトリガーを追加していくことで、Canavsへの描画などを行なってくれます。詳しくはこちらのサンプルを見てください。
React Konvaは、KonvaをReactで使いやすくするライブラリで、React Componentを宣言するようにCanvasを描画することができます。
以下が簡単な例です。(React Konvaのサンプルコードです。)

Stageコンポーネントから始まり、直下にLayer、そしてその配下に描画したいオブジェクトを並べていくと、実際にCanvasに描画されます。また、通常のReactコンポーネントと同じような使い勝手なので、状態管理してCanvasに描画するには、通常のDOMをレンダリングする場合と同じように、mapを使って描画していきます。
それでは今回は、konva reactを使って簡単な着せ替えアプリを作ってみたいと思います。

着せ替えアプリっぽいサンプルを作成

サンプルを作成しました。完成形はこちらです。

こちらが全体のソースコードです

React Konvaの導入

yarnでインストールします。

react-konvakonva が最低限必要なパッケージです。 use-image はURLから画像ファイルを読み、React Konvaの <Image /> コンポーネントに画像を読ませるためのhookです。

画像の描画

Canvasで画像を描画するには、React Konvaの <Image image={img} /> コンポーネントを使用するのですが、propsに渡す画像は、 CanvasImageSource という型になっています。

これらの型が意味するところはMDNで解説されているので詳しくは省略しますが、Canvas自体が画像を描画するには CanvasImageSource 型が必要となるため、React Konvaでもこの型で渡す必要があるのです。
今回はPNG画像を表示するのですが、その場合はimg要素に画像を読み込ませ、そのrefをImageコンポーネントに渡す必要があります。その実装の手間を省くため、konvajsが直々に公開している use-image hookです。

このhookはシンプルなソースコードなので一読して欲しいのですが、imgタグを生成し、そのrefを返しています。ただ、エラーハンドリングもやってくれているので、おそらくこのhookを使った方が、楽に実装できるのではないかなと思います。
今回は、 PartImage というコンポーネントを作り、ここで useImage hookを使って画像を取得し、 <Image /> コンポーネントを返しています。
以下は、先ほどのコードで実際に使っている部分のコードの切り抜きです。

 

stateによるCanvas描画

このサンプルでは stageParts というステートがCanvasに描画すべき値を持っているので、このstateの変化に応じてStageの内容を書き換えています。以下がその部分です。

stateをmapして、React Konvaで用意されたコンポーネントをを返していくだけで、Canvasに描画されていきます。通常のDOMと同じように、stateが変更されれば、Canvas内の描画も更新されるようになっているため、Reactに慣れているととても分かりやすいインターフェイスです。

レスポンスシブ対応

Stageのpropsには、widthとheightの他に、scaleX、scaleYも指定することができます。このスケールを設定することで、Canvas内を拡大・縮小することができます。例えば、次のようにスケールを0.5にすると、Canvas内は半分に縮小されて表示されるため、縦横ともに、実際の倍の1000ピクセル分の領域まで描画することができます。

この仕組みを使って、レスポンシブ対応をしてみました。その部分に関連するコードです。

ウインドウサイズの変更を契機に、親divのサイズを取得し setStageSize() でセットします。このサイズは直接Stageのwidthとheightに入ります。そして、scaleは stageSize / BASE_SIZE で求めます。これで、Stageのサイズが変化しても、Stage内はそのまま拡大・縮小されて表示できるようになりました。

画像のエクスポート

Stageの画像をエクスポートするには、Stageのrefを取得し、 toDataURL() を呼び出します。これはCanvasの関数で、Canvasに描画されている内容を画像化したData URIを取得することができます。
デフォルトではPNG画像が取得できるため、後はダウンロードしたり、どこかへアップロードしたりすることができます。今回は、ローカルにダウンロードするように実装しました。こちらが該当部分を切り抜いたソースです。

さいごに

React Konvaは、Reactの状態管理の仕組みと親和性が高く、アプリケーションに組み込みやすいことが分かりました。今後はReact Konvaが内部的にどのような仕組みCanvasに描画しているか、またそのレンダリングコストについても調査したいと思います。

おすすめ書籍

Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

blog-page_footer_336




blog-page_footer_336




-FrontEnd
-,

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

rails

Rails 7でフロントエンド開発が大きく変わる

1 はじめに1.1 脱Node.jsの経緯2 Rails 7.0でのアセット管理3 propshaft4 importmap-rails4.1 JavaScript CDN経由でのnpmパッケージの利 ...

Next.js 入門してみた

1 はじめに1.1 なぜNext.jsなのか?2 Next.jsとは何か2.1 Static Site Generation (SSG)2.1.1 Incremental Static Regener ...

react-icon

react-intl (Format.js) を使ってi18n対応

1 はじめに2 react-intlとは?3 react-intlの導入4 使い方4.1 IntlProviderの実装4.2 メッセージ定義4.3 <Foramatted*>コンポーネン ...

react-icon

React Hook Form (v7) とMUI (v5) だけでバリデーションを実装

1 はじめに2 バリデーションエラーをMUIのhelperTextに表示する2.1 バリデーション実装の全体感3 他のフィールドに関連するバリデーション4 CodeSandbox5 さいごに6 おすす ...

もうすぐ登場!Vue 3の変更点まとめ

1 はじめに2 仕様変更2.1 複数のv-modelが定義可能に2.2 template直下に複数のタグを記述可能に2.3 開始処理がcreateAppに2.4 scoped cssの仕様変更2.5 ...

フォロー

blog-page_side_responsive

2022年9月
 123
45678910
11121314151617
18192021222324
252627282930  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。