ろくろ遊びというタイトルでXに投稿されている方が居て、自分も描いてみたいなぁと思いました。
今日のろくろ遊び。
— 木佐貫洋平 プロカリンバ奏者 (@LimbaTrip) 2024年1月19日
今日のはなかなか気に入ってる。 pic.twitter.com/ceVCzTivRZ
ですが、なかなかろくろを触る機会もないので、アプリケーション化してみようと思い立ちました。
どんなものができた?
以下のリンクを参照してください。
コメントやXまで感想などいただけますと幸いです!
どのようにして作った?
以下はどんな作り方をしたのか興味のある方に参照いただければと思います。
このアプリは、PixiJSを利用して作成しました。
利用バージョンは、7.4.0です。
記事中のドキュメントのリンクが古いバージョンの場合もあるので注意してください。
PixiJSとは?
2D WebGLを利用して、高速に描画できるエンジンのようです。
250KB程度の容量でいい感じの描画ができるのが良いところなのかなと。
向いていない用途については、What PixiJS Is Not | PixiJSにまとまっているので、ご一読いただくのが良いかもしれません。
PixiJSの使い始め
Tutorial | PixiJSを読みながらまずは画面にウサギちゃんを表示していきます。
サンプルはimportしてNode.jsのモジュールとして読み込む内容になっていますが、PixiJSのCDNからjsを読み込む場合は、Getting Started | PixiJSの内容をベースに読み込み部分まで作れると良いかもしれません。
うまく動作させると、以下のように青色背景にウサギがクルクル回る画面ができます。
https://shikairo.gitlab.io/potters_wheel_paint/tutorial
ろくろが回る処理を作る
DynamicなGraphicの描画のサンプルにあったものを参考に実装します。
https://pixijs.com/playground?exampleId=graphics.dynamic
一番大事そうなのは、オブジェクトの描画位置を(0,0)から中心に変更する以下の処理かと思います。
これをしないと画面の左上を中心にぐるぐる回ってしまうので、ろくろが吹き飛んでしまいます。
thing.x = 800 / 2;
thing.y = 600 / 2;
https://pixijs.download/dev/docs/PIXI.Graphics.html#x
また、回転角度を指定する変数として、rotationとangleが用意されています。
rotationはラディアンで、angleは角度でそれぞれ指定できるので、理解しやすいものを利用するとよさそうです。
以下のように、app.tickerでバックグラウンドで繰り返し処理する中に加算する処理を入れることで、回転させることができます。
app.ticker.add*1.toString(16)}${parseInt(255 / (y + 1)).toString(16)}ff`
少し工夫した点としては、個別のGraphicsオブジェクトとして色を作ることで、それぞれのオブジェクトのクリックイベントからfillColorを取得できるようにしています。
これにより、簡単に前述の線を書き込む処理に色の情報を渡すことができました。
回転速度を変更できる処理を作る
書き終わった後で最後に高速で回転させて見せるのがいい感じだったので、回転速度も変えられるようにします。
Playground | PixiJSのSliderのサンプルがほぼそのまま使えます。onDragXXXを探してください。
保存できる処理を作る
さて、一通り書き込むための処理は作れたので、あとは保存できる処理を作ることができれば良さそうです。
データを保存するための関数としてはPIXI.CanvasExtractが用意されているようです。
imageかbase64形式の2つを選べるようで、imageを利用する場合は、Base64のBlobが入ったimageタグが生成されるので、利用用途によって使い分けるのがよさそうです。
ただし、この関数は動画形式では保存できなさそうで、画像形式(jpeg or webp)で保存することになりそうです…
format string <optional> Image format, e.g. "image/jpeg" or "image/webp".
imageの引数を見る感じ、Frameでの指定もできるようなので、動きのあるページの一部を切り取るように利用されるのが想定されているのでしょうか。
感想
意外と簡単にペイントアプリをpixi.jsで作ることができました。
ただ、動画で画像が保存できないなど、自前実装をしないといけない部分があるので、今後の課題としておきます。
pixiの使い方もわかってきたので、他にも動きのあるページを作る際に知識を役立てられそうです。
*1:delta) => {
things.rotation += 0.1 * delta;
});
ろくろに線を書き込める処理を作る
以下のようにeventModeを指定することでクリックイベントを受け付けるようにします。
なお、現在はGraphicsにも指定できるようですので、当たり判定の処理が楽になりそうです。
app.stage.eventMode = "static";
まずは点を書き込む処理としてdrawRectを使ってみます。
この際、ろくろは回転しているので、描画位置のx,yを計算して与えてあげる必要があります。
座標の回転 - 高精度計算サイトにて公式が公開されているので、ありがたく利用させていただきました。
sin, cos関数はMathライブラリを利用しております。
こちらの関数はラディアンで回転角度を与える必要があるので、rotationを利用しました。
また、クリックしている間だけ描画させたいので、クリックイベントに応じて描画するかどうかのフラグを変更しています。
app.stage.on("pointerdown", () => {
DRAW_FLAG = true;
});
app.stage.on("pointerup", () => {
DRAW_FLAG = false;
});
https://pixijs.download/v7.4.0/docs/PIXI.html#EventSystemFeatures
ひとまず書き込めるようになったら、以下のようにtickerに書き込み処理を追加すれば、連続で描画できるようになります。
app.ticker.add((delta) => {
things.rotation += 0.1 * delta;draw();
});
色を変えられる処理を作る
あまり色数は作れませんでしたが、カラーパレットを作ってみます。
fillColorとして16進数で値を渡す必要があるので、16進数に変換する処理を自作してみました。
toString関数に引数を渡すと16進数として文字列に変換してくれるのを初めて知って便利だなと思いました。
`0x${parseInt(255 / (x + 1