🎨

CustomPainterについて学ぶ【ARメイクの実装サンプルもあるよ】

2022/06/19に公開

こんにちは、sh0です。
今回の記事は「CustomPainter」について勉強したことをまとめます。
勉強するだけだとつまらないので、タイトルの通りARメイクのプロトタイプを作ってみました。

コードだけ見たい方はこちら
※勉強用のコードなのでかなり汚いです

CustomPainterって何

CustomPainter について簡単にまとめると
「図形データを与えて、Canvas上に描写する」ための抽象クラスで、自作する際には CustomPainter を継承したクラスを作成します。

使い方は CustomPaint というWidgetがあってこいつにセットして使います。

CustomPaint(painter: MyPainter())

CustomPainterを継承して自作する

CustomPainter を継承する際には、2つのメソッドをoverrideする必要があります。

class MyPainter extends CustomPainter {

  /// 描画処理を記述する
  
  void paint(Canvas canvas, Size size) {}
  
  
  bool shouldRepaint(covariant CustomPainter oldDelegate) {}
}

描画処理を記述する

描画処理の基本的な流れは下記のようになります。

  1. 描画する時の設定( Paintクラス
  2. 図形の情報( RectクラスPathクラス 、etc...)
  3. 1と2の値を使って、 Canvasクラス の描画メソッドを呼ぶ

実際にコードを見ると分かりやすいので、円の場合と四角形の場合、三角形の場合のコードを記載します。

円の場合


void paint(Canvas canvas, Size size) {
  // 円(塗りつぶし)
  // 円の色を設定(Paint)
  final filledCirclePaint = Paint()..color = Colors.green;
  // NOTE: 円の場合、専用の描画メソッドがあるので図形の情報は必要ありません
  // Canvasクラスの描画メソッドを呼ぶ
  canvas.drawCircle(
    Offset(size.width / 2, size.height / 4),
    size.width / 4,
    filledCirclePaint,
  );
  
  // 円(枠線)
  // 円の色や枠線の太さを設定(Paint)
  final outlinedCirclePainter = Paint()
    ..color = Colors.red
    ..strokeCap = StrokeCap.round
    ..style = PaintingStyle.stroke
    ..strokeWidth = 2;
  // Canvasクラスの描画メソッドを呼ぶ
  canvas.drawCircle(
    Offset(size.width / 2, size.height / 4 * 3),
    size.width / 4,
    outlinedCirclePainter,
  );
}

四角形の場合


void paint(Canvas canvas, Size size) {
  // 四角形(塗りつぶし)
  // 四角形の色を設定(Paint)
  final rectPaint = Paint()..color = Colors.blue;
  // 四角形の情報を作成
  final rect = Rect.fromLTWH(0, 0, size.width, size.height);
  // Canvasクラスの描画メソッドを呼ぶ
  canvas.drawRect(rect, rectPaint);
  
  // 枠線の方は円の場合と同様にPaintの設定をすれば実装できるので割愛します
}

三角形の場合

三角形の場合は、専用の描画メソッドないので図形のデータを用意する必要があります。


void paint(Canvas canvas, Size size) {
  // 三角形(塗りつぶし)
  // 三角形の色を設定(Paint)
  final filledTrianglePaint = Paint()..color = Colors.purpleAccent;
  
  // 三角形の頂点から左回りでPathを生成(各点のx, y座標を渡しています)
  final filledTrianglePath = Path();
  filledTrianglePath.moveTo(size.width/2, size.height/5); // 始点
  filledTrianglePath.lineTo(size.width/4, size.height/5*2);
  filledTrianglePath.lineTo(size.width/4*3, size.height/5*2);
  filledTrianglePath.close();
  
  // Canvasクラスの描画メソッドを呼ぶ
  canvas.drawPath(filledTrianglePath, filledTrianglePaint);
  
  // 枠線の方は円の場合と同様にPaintの設定をすれば実装できるので割愛します
}

まとめ

今回は CustomPainter を使って図形を描画してみたわけですが、勉強を始める前に思っていたほど難しくなくて理解しやすかったですね。
上記の基本的な図形だけでなく、複雑な図形もいろいろ描画できるので是非試してみてください!
(直線を描画するメソッドとか、楕円を描画するメソッドとかもありました)
個人的には CustomPainter を使ってお絵描きアプリとかも作れそうなのでトライしたいと思います。

おまけ

本文で紹介したサンプルコードだけだと、アウトプットとしてはつまらないなと思ったので冒頭にも書きましたが、ARメイクのプロトタイプを作ってみました。
ソースコード

やった内容としては

  • 顔検出はGoogle様のお力を借りました
  • こちらのpackageを使うと、顔の検出と顔のパーツの座標が取れるので、一番やりやすかった唇の座標をPathクラス に渡して図形の情報を作成(三角形の場合と同様)
  • Paintクラス の設定で塗りつぶし

という感じです。
こちらも思っていたよりも単純で、 CustomPainter の使い方が分かっていれば30分くらいでサクッと実装できました。

とりあえず動くものを作った感じなので、改善点等あればコメントお願いします!

Discussion