2022年10月16日 星期日

Flutter學習-Canvas組件

 Flutter的自定義繪圖,主要利用CustomPaint這個部件,CustomPaint的建構式如下。

const CustomPaint({
Key? key,
this.painter, //位於child下的背景
this.foregroundPainter, //位於child上的前景
this.size = Size.zero, //大小,如果有設置child,就以child的大小為主
this.isComplex = false, //是否混合
this.willChange = false, //是否在下一幀改變
Widget? child,
}) : assert(size != null),
assert(isComplex != null),
assert(willChange != null),
assert(painter != null || foregroundPainter != null || (!isComplex && !willChange)),
super(key: key, child: child);

一般常用的屬性是painter或是child。

child就是你要放置的內容,可以透過這個child來放置一下Flutter已經設計好,不需要自行繪製的部件。

painter裡的值,要放的是繪製的方法,透過繼承了CustomPainter父類別的新類別,來提供繪製的方法。如下列例子:

class myPainter extends CustomPainter{
@override
void paint(Canvas canvas, Size size) {
// TODO: implement paint
}

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
throw UnimplementedError();
}

這裡面有兩個必要的建立的方法,先說shouldRepaint(covariant CustomPainter oldDelegate),這地方主要在設定繪圖物件有更新或未更新時,要採取的方式。


第二個paint(Canvas canvas, Size size)有兩個參數,Canvas指的是畫布,而Size指的是上面CustomPaint上設置的child或是size長及寬。

Canvas提供的方法很多,以下介紹幾個。

canvas.save() 保存
canvas.saveLayer() 創建另一個圖層
canvas.restore() 放置於canvas.save() canvas.saveLayer() 後,將圖層合成
canvas.translate(double dx, double dy) 畫布平移至某位置
canvas.scale(double sx, [double sy]) 畫布縮放
canvas.rotate(double radians) 旋轉畫布
canvas.skew(double sx, double sy) 斜切


繪製部份
(一)畫點
Canvas.drawPoints(PointMode pointMode, List points, Paint paint);
參數說明:
PointMode pointMode:繪製模式(有 PointMode.pointsPointMode.lines、 PointMode.polygon三種),
List points:位置 ,採用陣列,如以下設定 [Offset(300, 500)],
Paint paint:畫筆設定

canvas.drawPoints(PointMode.lines,[Offset(300, 500),Offset(400, 500)],paint);

(二)畫線
Canvas.drawLine(Offset p1, Offset p2, Paint paint);
參數說明:

Offset p1:起點位置

Offset p2:終點位置

Paint paint:畫筆設定

(三)畫矩形
Canvas.drawRect(Rect rect, Paint paint)
參數說明:

Rect rect:矩形的位置及長寬設定

根據四個位置設定矩形 Rect.fromLTRB(this.left, this.top, this.right, this.bottom)

根據左上角位置及寬高設定矩形 Rect.fromLTWH(double left, double top, double width, double height)


根據中心位置及寬高設定矩形 Rect.fromCenter( Offset center ,double width, double height )

根據內接圓 ,生成正方形,設定矩形 Rect.fromCircle(Offset center, double radius )

根據左上角及右下角位置,設定矩形 Rect.fromPoints(Offset a, Offset b)


Paint paint:畫筆設定

(四)畫圓形
Canvas.drawCircle(Offset c, double radius, Paint paint),

參數說明:
Offset c:圓心位置
double radius:圓半徑

Paint paint:畫筆設定


(五)繪製橢圓

drawOval(Rect rect, Paint paint)

參數說明:
Rect rect:矩形設定(可見上面第三項)

Paint paint:畫筆設定


(六)繪製圓弧

drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint)

參數說明:
Rect rect:矩形設定(可見上面第三項)
double startAngle:開始角度,以x軸為0起算的弧度制,弧度制的算法 (角的度數 x pi/180)
double sweepAngle:圓環的角度,弧度制
bool useCenter:終點是否和圓心連接
Paint paint:畫筆設定

Flutter Canvas學習之繪圖篇 | IT人 (iter01.com)

https://juejin.cn/post/7061893652242989064

http://soiiy.com/flutter/11823.html

https://zhuanlan.zhihu.com/p/424768534


import 'package:flutter/material.dart';
import 'dart:ui' as ui;

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


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

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '畫圖練習',
theme: ThemeData(

primarySwatch: Colors.blue,
),
home: const MyHomePage(title: '繪圖練習'),
);
}
}

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

final String title;

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

class _MyHomePageState extends State<MyHomePage> {


@override
Widget build(BuildContext context) {

return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
//利用custompaint繪圖
body:CustomPaint(
//繪製圖的大小
size: Size(200.0,200.0),
//圖的前景畫法
painter: DrawPainter(),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

class DrawPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
paint.style = PaintingStyle.stroke;
paint.strokeWidth = 10;
canvas.drawRRect(RRect.fromRectAndRadius(const Rect.fromLTWH(0, 0, 200, 150), const Radius.circular(10)), paint);
canvas.drawPoints(
ui.PointMode.points,
[
Offset(100, 100),
Offset(250, 180),
Offset(200, 300),
],
paint);

}

沒有留言:

張貼留言