【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. flutter

    【Flutter】GoogleMapを使用したアプリの開発について P…

  2. 【Widget of the Week】#3 Wrap

  3. flutter

    【Flutter】GoogleMapを使用したアプリの開発について P…

  4. flutter

    【Flutter】StateNotifierProviderで状態管理…

  5. 【Widget of the Week】#1 Safe Area

  6. flutter

    【Flutter】Flutter実装メモ showModalBotto…

最近の記事

制作実績一覧

  1. Checkeys