일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Flutter
- Maui
- 깃허브
- 마우이
- typescript
- Animation
- spring boot
- GitHub
- 바인딩
- .NET
- React JS
- 애니메이션
- 파이어베이스
- page
- Binding
- 함수
- 오류
- 리엑트
- Firebase
- JavaScript
- db
- AnimationController
- MS-SQL
- 자바스크립트
- listview
- 플러터
- MVVM
- HTML
- MSSQL
- 닷넷
Archives
- Today
- Total
개발노트
64.[Flutter] CustomPainter로 도형 그리기 (Apple Watch 앱 따라해보기) 본문
반응형
CustomPainter
CustomPainter는 Flutter 프레임워크에서 사용자 지정 그래픽을 그리는 데 사용되는 클래스입니다. 이 클래스를 사용하면 사용자가 직접 화면에 그래픽을 그릴 수 있습니다. CustomPainter를 사용하면 사용자 지정 그래픽을 그리기 위해 주어진 화면 영역에 대한 접근이 가능합니다.
CustomPainter를 사용하는 일반적인 프로세스는 다음과 같습니다:
- CustomPainter 클래스 구현: 사용자 정의 그래픽을 그리기 위해 CustomPainter 클래스를 확장하여 사용자 지정 그래픽을 정의합니다. CustomPainter 클래스는 paint() 메서드를 구현해야 합니다. 이 메서드에서 그래픽을 그립니다.
- CustomPainter 인스턴스 생성: CustomPainter 클래스의 인스턴스를 생성하고 사용자 지정 그래픽을 그릴 때 필요한 모든 매개 변수를 전달합니다.
- 그리기 위한 위젯에 CustomPainter 적용: CustomPainter 인스턴스를 사용하여 그릴 위젯에 적용합니다. 주로 CustomPaint 위젯을 사용하여 CustomPainter를 적용합니다. CustomPaint 위젯은 painter 속성을 통해 CustomPainter를 받습니다.
- 화면에 그래픽 그리기: CustomPainter에서 구현한 그리기 로직에 따라 화면에 그래픽이 그려집니다. Flutter 프레임워크는 이를 자동으로 처리합니다.
CustomPainter를 사용하면 다양한 종류의 그래픽을 그릴 수 있습니다. 이를 통해 사용자 지정 시각적 요소를 만들거나 복잡한 애니메이션을 구현할 수 있습니다. 주로 CustomPainter는 사용자 지정 그래픽, 차트, 애니메이션 및 UI 효과를 구현하는 데 사용됩니다.
CustomPaint 로 간단한 도형 그리기 예시.
CanvasScreen.dart (StatefulWidget 부분)
import 'package:flutter/material.dart';
class CanvasScreen extends StatefulWidget {
static String routeName = "canvus";
static String routeURL = "canvus";
const CanvasScreen({super.key});
@override
State<CanvasScreen> createState() => _CanvasScreenState();
}
class _CanvasScreenState extends State<CanvasScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
title: const Text("Canvas"),
),
body: Center(
child: CustomPaint(painter: Painter(), size: const Size(400, 400)),
),
);
}
}
Painter.cs (CustomPainter 부분)
class Painter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
//사각형
final rect = Rect.fromCenter(
center: center, width: 400, height: 200); //사각형 정보를 갖는 객체
canvas.drawRect(
rect, //Rect 사각형 객체
Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = 5);
//원
canvas.drawCircle(
Offset((size.width / 2) / 3, (size.height / 2)), //중심점 위치
50, //반지름 길이
Paint()
..color = Colors.blue //색상
..style = PaintingStyle.stroke //비어있는 스타일
..strokeWidth = 10); //두께
//삼각형 (점을 잇는 직선으로 그리기)
canvas.drawPath(
Path()
..moveTo(size.width / 2.1, size.height / 2.6) //첫 시작점
..lineTo(size.width / 2 / 1.4, size.height / 1.6) //다음 점 위치
..lineTo(size.width / 1.65, size.height / 1.6) //다음 점 위치
..lineTo(size.width / 2.1, size.height / 2.6) //다음 점 위치
..close(),
//다음 점이 없음을 알리고 moveTo(시작점)을 이어줌
Paint()
..color = Colors.pinkAccent
..style = PaintingStyle.stroke
..strokeWidth = 10);
//사각형
canvas.drawRect(
Rect.fromLTRB(size.width / 1.4, size.height / 2.6, size.width / 1.05,
size.height / 1.6),
Paint()
..color = Colors.orange //도형 색상
..style = PaintingStyle.stroke //도형 색 채우기 없음
..strokeWidth = 10); //테두리 넓이
//canvas.drawLine(); 직선
//canvas.drawRect(); 사각형
//canvas.drawPath(); 경로로 그리기
//canvas.drawCircle(); 원
//canvas.drawArc(); 곡선
//canvas.drawParagraph(); //텍스트 문단
//canvas.drawImage(); 이미지
//문자 그리기는 TextPainter 사용
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true; //return 값에 따라 그림을 다시 그림 (false면 한번만 그림)
// true 이기 때문에 CustomPainter 인스턴스가 생성될 때마다 항상 그림을 다시 그려야 함을 의미함
}
}
CustomPaint 와 Animation 응용 예시. (움직이는 도형)
CustomPainter 와 AnimationController를 응용하여 Apple Watch 앱을 만들어 봅니다.
- 출처: 노마드코더:https://nomadcoders.co/
AppleWatchScreen.dart (StatefulWidget 부분)
import 'dart:math';
import 'package:flutter/material.dart';
class AppleWatchScreen extends StatefulWidget {
static String routeName = "applewatch";
static String routeURL = "applewatch";
const AppleWatchScreen({super.key});
@override
State<AppleWatchScreen> createState() => _AppleWatchScreenState();
}
class _AppleWatchScreenState extends State<AppleWatchScreen>
with SingleTickerProviderStateMixin {
late final AnimationController _animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 2000),
)..forward();
late Animation<double> _animation =
Tween(begin: 0.0, end: 1.5).animate(_curvedAnimation);
late Animation<double> _animation2 =
Tween(begin: 0.0, end: 1.5).animate(_curvedAnimation);
late Animation<double> _animation3 =
Tween(begin: 0.0, end: 1.5).animate(_curvedAnimation);
late final CurvedAnimation _curvedAnimation = CurvedAnimation(
parent: _animationController,
curve: Curves.bounceOut,
);
@override
void initState() {
_animationController.addListener(() {});
_animationController.addStatusListener((status) {});
_animateValues();
super.initState();
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _animateValues() {
final newBegin = _animation.value;
final random = Random();
final newEnd = random.nextDouble() * 2.0;
final random2 = Random();
final newEnd2 = random2.nextDouble() * 2.0;
final random3 = Random();
final newEnd3 = random3.nextDouble() * 2.0;
setState(() {
_animation =
Tween(begin: newBegin, end: newEnd).animate(_curvedAnimation);
_animation2 =
Tween(begin: newBegin, end: newEnd2).animate(_curvedAnimation);
_animation3 =
Tween(begin: newBegin, end: newEnd3).animate(_curvedAnimation);
});
_animationController.forward(from: 0);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
elevation: 0,
title: const Text("Apple Watch"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return CustomPaint(
painter: AppleWatchPainter(
progress: _animation.value,
progress2: _animation2.value,
progress3: _animation3.value,
),
size: const Size(200, 200),
);
},
),
Padding(
padding: const EdgeInsets.all(50),
child: ElevatedButton(
onPressed: _animateValues, child: const Icon(Icons.refresh)),
)
],
),
),
);
}
}
AppleWatchPainter.dart (CustomPainter 부분)
class AppleWatchPainter extends CustomPainter {
final double progress;
final double progress2;
final double progress3;
AppleWatchPainter(
{required this.progress,
required this.progress2,
required this.progress3});
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
const startingAngle = -0.5 * pi;
final redArcRect = Rect.fromCircle(center: center, radius: 100);
final redArcPaint = Paint()
..color = Colors.pink
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..strokeWidth = 20;
canvas.drawArc(
redArcRect,
startingAngle,
progress * pi,
false,
redArcPaint,
);
final redArcRect2 = Rect.fromCircle(center: center, radius: 78);
final redArcPaint2 = Paint()
..color = Colors.limeAccent.shade700
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..strokeWidth = 20;
canvas.drawArc(
redArcRect2,
startingAngle,
progress2 * pi,
false,
redArcPaint2,
);
final redArcRect3 = Rect.fromCircle(
center: Offset(size.width / 2, size.height / 2), radius: 56);
final redArcPaint3 = Paint()
..color = Colors.lightBlue
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..strokeWidth = 20;
canvas.drawArc(
redArcRect3,
startingAngle,
progress3 * pi,
false,
redArcPaint3,
);
}
@override
bool shouldRepaint(covariant AppleWatchPainter oldDelegate) {
return oldDelegate.progress != progress;
}
}
반응형
'앱 개발 > Flutter' 카테고리의 다른 글
Comments