LoginSignup
6
3

More than 1 year has passed since last update.

Fabric.jsでお絵かきアプリをつくる

Last updated at Posted at 2022-12-13

この記事は C3 Advent Calendar 2022 14日目の記事です

はじめに

ふぃるです。
C3 では Web フロントエンドを中心で色々開発したり、曲を作ったりしています。
最近、原神にはまって卒業研究がなかなか進みません。助けてください。

Fabric.jsとは

その名の通り、JavaScript のライブラリです。
お絵かきをすることができます。
使い方としては、お題をもとにどんな絵を書いてるか当てるゲームや、お絵かき伝言ゲームなどがあります。なんか聞いたことがあるゲームだって?気のせいじゃないですか?

公式のホームページはこちら
Tutorial や Docs などがありますが微妙に見づらいので、ここで色々紹介します。

デモ

React + TypeScript + MUI でデモを作りました。
https://handwritten-app.vercel.app/

Github の URL も一応載せておきます。
git clone して煮るなり焼くなり好きにしてもらっても大丈夫です。
https://github.com/citrus-candy/handwritten-app

デモでは以下の機能を実装しています。

  • Undo & Redo
  • Clear
  • ブラシの色変更
  • ブラシの太さ変更

この機能について、どのような実装をしているのか紹介していきます。

Undo & Redo

Undo と Redo に関しては Fabric.js に実装されていないので、自前で実装する必要があります。

Undo

const undo = () => {
  if (canvas !== undefined && canvas._objects.length > 0) {
    const copyArray = [...canvasHistory]
    copyArray.push(canvas._objects.pop()!)
    canvasHistory = copyArray
    canvas.renderAll()
  }
}

canvas._objects には今までに書いた線がオブジェクトとして保存されているので、それを利用します。

Redo

useEffect(() => {
  canvas?.on('object:added', () => {
    if (!isRedoing) {
      canvasHistory = []
    }
    isRedoing = false
  })
}, [canvas])

const redo = () => {
  if (canvas !== undefined && canvasHistory.length > 0) {
    isRedoing = true
    canvas.add(canvasHistory.pop()!)
  }
}

canvas.add を使って、Undo した線をもとに戻します。

add(...object) → {self}
Adds objects to collection, Canvas or Group, then renders canvas (if renderOnAddRemove is not false). in case of Group no changes to bounding box are made. Objects should be instances of (or inherit from) fabric.Object Use of this function is highly discouraged for groups. you can add a bunch of objects with the add method but then you NEED to run a addWithUpdate call for the Group class or position/bbox will be wrong.
Parameters:

Name Type Attributes Description
object fabric.Object < repeatable > Zero or more fabric instances

Returns:
thisArg
Type: Self

http://fabricjs.com/docs/fabric.Canvas.html#add

また、object:added で線を書くイベントを取得することができます。

Object related

  • object:added — fired after object has been added

https://github.com/fabricjs/fabric.js/wiki/Working-with-events

Clear

const clear = () => {
  if (canvas !== undefined) {
    canvas.clear()
    canvasHistory = []
    canvas.setBackgroundImage(bgImageUrl, () => canvas.renderAll())
  }
}

canvas.clear() でキャンバスを初期化します。

clear() → {fabric.Canvas}
Clears all contexts (background, main, top) of an instance
Returns:
thisArg
Type: fabric.Canvas

また、デモでは使っていませんが canvas.setBackgroundImage() でキャンバスに背景画像を設定することができます。

setBackgroundImage(image, callback, optionsopt) → {fabric.Canvas}
Sets background image for this canvas
Parameters:

Name Type Attributes Description
image fabric.Image or String fabric.Image instance or URL of an image to set background to
callback function Callback to invoke when image is loaded and set as background
options Object < optional > Optional options to set for the background image.

Returns:
thisArg
Type: fabric.Canvas

http://fabricjs.com/docs/fabric.Canvas.html#setBackgroundImage

線の色の変更

useEffect(() => {
  if (canvas !== undefined) {
    canvas.freeDrawingBrush.color = selectColor
  }
}, [canvas, selectColor])

canvas.freeDrawingBrush.color の値を変更することで、線の色を変えることができます。

color :String
Color of a brush
Type:

  • String

http://fabricjs.com/docs/fabric.BaseBrush.html#color

線の太さの変更

useEffect(() => {
  if (canvas !== undefined) {
    canvas.freeDrawingBrush.width = brushwidth
  }
}, [canvas, brushwidth])

canvas.freeDrawingBrush.width の値を変更することで、線の太さを変えることができます。

width :Number
Width of a brush, has to be a Number, no string literals
Type:

  • Number

http://fabricjs.com/docs/fabric.BaseBrush.html#width

おわりに

Fabric.js を使えば、お絵かきが簡単に実装できます。
他にも、キャンバスのオブジェクトを JSON でエクスポートしたり、逆にインポートができたりします。

明日は、西園寺やきしゃもさんの「C言語におけるポインタの文法について」です!

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3