본문 바로가기
flutter

[flutter] CustomPainter로 그래프 만들기

by teamnova 2024. 10. 16.
728x90

안녕하세요,

 

오늘은 CustomPainter로 그래프를 그려보도록 하겠습니다. 

 

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '그래프 예제',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('그래프 그리기'),
        ),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: CustomPaint(
              size: Size(300, 200), // 캔버스 크기
              painter: LineChartWithPointLabelsPainter(),
            ),
          ),
        ),
      ),
    );
  }
}

class LineChartWithPointLabelsPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // 차트 배경
    final Paint backgroundPaint = Paint()
      ..color = Colors.white
      ..style = PaintingStyle.fill;

    // 배경 그리기
    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), backgroundPaint);

    // 차트를 그릴 선
    final Paint linePaint = Paint()
      ..color = Colors.blue
      ..strokeWidth = 2
      ..style = PaintingStyle.stroke;

    // 차트의 데이터 (x, y 좌표)
    final points = [
      Offset(0, size.height * 0.8),   // 시작점
      Offset(size.width * 0.2, size.height * 0.6),
      Offset(size.width * 0.4, size.height * 0.5),
      Offset(size.width * 0.6, size.height * 0.3),
      Offset(size.width * 0.8, size.height * 0.4),
      Offset(size.width, size.height * 0.2), // 끝점
    ];

    final yValues = [1.0, 1.5, 2.0, 2.5, 2.0, 1.0]; // 각 점의 y축 값 (임의 값)

    // 선 그리기
    final path = Path()..moveTo(points[0].dx, points[0].dy);
    for (var point in points.skip(1)) {
      path.lineTo(point.dx, point.dy);
    }
    canvas.drawPath(path, linePaint);

    // 좌표 점 표시
    final Paint dotPaint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.fill;

    for (var point in points) {
      canvas.drawCircle(point, 4, dotPaint); // 각 점을 원으로 그림
    }

    // 각 점 위에 값을 표시
    final TextPainter textPainter = TextPainter(
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
    );

    for (int i = 0; i < points.length; i++) {
      textPainter.text = TextSpan(
        text: yValues[i].toString(),
        style: TextStyle(color: Colors.black, fontSize: 12),
      );
      textPainter.layout();
      final xPosition = points[i].dx;
      final yPosition = points[i].dy - 15; // 점 위에 여백을 주어 값 표시
      textPainter.paint(canvas, Offset(xPosition - textPainter.width / 2, yPosition));
    }

    // X축 라벨 추가
    final List<String> xLabels = ['0', '1', '2', '3', '4', '5'];
    for (int i = 0; i < xLabels.length; i++) {
      textPainter.text = TextSpan(
        text: xLabels[i],
        style: TextStyle(color: Colors.black, fontSize: 12),
      );
      textPainter.layout();
      final xPosition = (size.width / (xLabels.length - 1)) * i.toDouble(); // int를 double로 변환
      final yPosition = size.height + 5.0; // x축의 위치
      textPainter.paint(canvas, Offset(xPosition - textPainter.width / 2, yPosition));
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false; // 그래프 업데이트 필요 시 true로 변경
  }
}

 

 

결과 화면입니다.