【Flutter】CustomPainterを使い、図形を描画

flutter

1. 概要

今回は図形を描く内容となります。

対象としては開発を1年程やってて自分で最初から開発してみたい方になります。そのため細かい用語などの説明はしません。

2. プロジェクトの準備

2-1. プロジェクトを作成

3. ソースコード

3-1. lib/data/data.dart

List<double> data = [];

3-2. lib/views/my_painter.dart

import 'package:custom_painter_demo/data/data.dart';
import 'package:flutter/material.dart';

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint paintLine = Paint()
      ..strokeWidth = 3
      ..color = Colors.white;
    Paint paintCircle = Paint()..color = Colors.red;

    double padding = 50;

    int verticalLine = 6;
    double marginOfBothSide = size.width - (2 * padding);
    drawVerticalLines(
        paintLine, canvas, size, padding, verticalLine, marginOfBothSide);

    int horizontalLine = 6;
    double marginOfUpDown = size.height - (2 * padding);
    drawHorizontalLines(
        paintLine, canvas, size, padding, horizontalLine, marginOfUpDown);

    drawPoints(paintCircle, canvas, padding, verticalLine, marginOfBothSide,
        marginOfUpDown);
  }

  void drawVerticalLines(Paint paint, Canvas canvas, Size size, double padding,
      int verticalLine, double marginOfBothSide) {
    for (int i = 0; i < verticalLine + 1; i++) {
      canvas.drawLine(
          Offset((marginOfBothSide / verticalLine * i + padding), padding),
          Offset((marginOfBothSide / verticalLine * i + padding),
              size.height - padding),
          paint);
    }
  }

  void drawHorizontalLines(Paint paint, Canvas canvas, Size size,
      double padding, int horizontalLine, double marginOfUpDown) {
    for (int i = 0; i < horizontalLine + 1; i++) {
      canvas.drawLine(
          Offset(padding, (marginOfUpDown / horizontalLine * i + padding)),
          Offset(
              size.width - 50, (marginOfUpDown / horizontalLine * i + padding)),
          paint);
    }
  }

  void drawPoints(Paint paint, Canvas canvas, double padding, int verticalLine,
      double marginOfBothSide, double marginOfUpDown) {
    int dataLength = data.length - 1;
    for (int i = 0; i < dataLength + 1; i++) {
      canvas.drawCircle(
          Offset((marginOfBothSide / verticalLine * i + padding),
              (marginOfUpDown / verticalLine * data[i] + padding)),
          10,
          paint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

3-3. lib/views/home.dart

import 'package:custom_painter_demo/data/data.dart';
import 'package:custom_painter_demo/views/my_painter.dart';
import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  void _addData() {
    if (_counter < 7) {
      data.add(_counter.toDouble());
      _counter++;
    } else {
      data.clear();
      _counter = 0;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.green.shade900,
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: CustomPaint(
            size: const Size(double.infinity, double.infinity),
            painter: MyPainter()),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      floatingActionButton: FloatingActionButton(
        onPressed: _addData,
        tooltip: 'Paint a circle',
        child: const Icon(Icons.add),
      ),
    );
  }
}

3-4. lib/main.dart

import 'package:custom_painter_demo/views/home.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Custom Painter'),
    );
  }
}

4. 結果

5. 備考

今回はLineやCircleを描いてみましたが、他にも色々描けるようなので応用していけたらと思います。

6. 参考

投稿者プロフィール

Sondon
開発好きなシステムエンジニアです。
卓球にハマってます。

関連記事

  1. 【Widget of the Week】#10 Table

  2. flutter

    【Flutter】KotlinでNative側を実装しFlutterと…

  3. flutter

    Flutterのすゝめ

  4. flutter

    【Flutter】Cloud Firestoreと連携

  5. flutter

    【Flutter】APIからデータを取得し画面に表示(Flutter,…

  6. flutter

    【Flutter】Pankoにあみだくじ機能を追加

最近の記事

  1. 日記アプリ第5回
  2. 日記アプリ第4回
  3. React
  4. 日記アプリ第3回
  5. 日記アプリ第2回
  6. 日記アプリ第1回

制作実績一覧

  1. Vivaya
  2. Checkeys