一、Canvas簡介
Canvas是Flutter中的繪圖類,它提供了一系列繪製2D圖形的方法和工具。例如,繪製直線,矩形,圓形等形狀。在使用Canvas之前,必須先創建一個CustomPaint類,它允許在其內部繪製自定義的圖形。
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: MyPainter(),
);
}
MyPainter是自定義Painter的子類,它繼承了PaintingContext抽象類,可以在自身的Canvas上繪製圖形元素。
二、Canvas的屬性和方法
Canvas提供了一系列用於創建和修改圖形的方法和屬性。
1. 繪製形狀
Canvas的常用圖形方法包括drawLine、drawRect、drawCircle、drawArc等。例如,以下代碼演示了如何使用Canvas繪製一個矩形:
@override
void paint(Canvas canvas, Size size) {
Rect rect = Rect.fromLTWH(0, 0, size.width, size.height);
Paint paint = Paint();
paint.color = Colors.red;
canvas.drawRect(rect, paint);
}
2. 設置畫筆屬性
Canvas的Paint類包含一系列用於設置和修改畫筆屬性的方法和屬性,例如color、strokeWidth、strokeCap、strokeJoin等。
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
paint.color = Colors.black;
paint.strokeWidth = 5;
paint.strokeCap = StrokeCap.round;
paint.strokeJoin = StrokeJoin.round;
canvas.drawLine(Offset.zero, Offset(size.width, size.height), paint);
}
3. 設置繪製文字的屬性
在Canvas中,TextPainter類用於繪製文本。可以使用TextStyle類設置文字的樣式,例如字體顏色、字體大小、字體樣式等。以下代碼演示了如何在Canvas中繪製文本:
@override
void paint(Canvas canvas, Size size) {
TextPainter textPainter = TextPainter(
text: TextSpan(text: "Hello World", style: TextStyle(color: Colors.black, fontSize: 20)),
textDirection: TextDirection.ltr,
);
textPainter.layout();
textPainter.paint(canvas, Offset(50, 50));
}
4. Matrix變換
使用Matrix可以進行Canvas上的幾何變換。常用的變換包括平移,旋轉,縮放。
@override
void paint(Canvas canvas, Size size) {
Rect rect = Rect.fromLTWH(0, 0, 100, 100);
Paint paint = Paint();
canvas.save();
canvas.translate(size.width / 2, size.height / 2); // 平移
canvas.rotate(pi / 4); // 旋轉
canvas.scale(2); // 縮放
canvas.drawRect(rect, paint);
canvas.restore();
}
三、Canvas的應用
Canvas可以用於很多應用場景,例如繪製圖表,製作自定義的UI組件,創建遊戲等。
1. 繪製圖表
Canvas可以繪製各種圖表,例如柱狀圖、餅狀圖、折線圖等。
以下代碼演示了如何使用Canvas繪製一個柱狀圖:
class BarChartPainter extends CustomPainter {
final List data;
BarChartPainter(this.data);
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = Colors.blue
..strokeWidth = 2;
double barWidth = size.width / data.length;
for (int i = 0; i < data.length; i++) {
double xPos = i * barWidth;
double barHeight = data[i] / 100 * size.height;
Rect rect = Rect.fromLTRB(xPos, size.height - barHeight, xPos + barWidth, size.height);
canvas.drawRect(rect, paint);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
class BarChart extends StatelessWidget {
final List data;
BarChart(this.data);
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: BarChartPainter(data),
size: Size(double.infinity, 200),
);
}
}
// Example usage:
BarChart([30, 50, 80, 20]);
2. 製作自定義的UI組件
使用Canvas,我們可以為我們的應用程序創建獨特的自定義UI組件。例如,我們可以使用Canvas創建帶有自定義繪圖的開關按鈕。
class CustomSwitchPainter extends CustomPainter {
final bool value;
CustomSwitchPainter(this.value);
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = value ? Colors.green : Colors.grey
..style = PaintingStyle.fill;
canvas.drawRRect(
RRect.fromRectAndRadius(Rect.fromLTWH(0, 0, size.width, size.height), Radius.circular(size.height / 2)),
paint);
double switchWidth = size.width / 2;
double offset = value ? size.width - switchWidth : 0;
Paint switchPaint = Paint()
..color = Colors.white
..style = PaintingStyle.fill;
canvas.drawCircle(
Offset(offset, size.height / 2),
size.height / 2 - 2,
switchPaint,
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
class CustomSwitch extends StatefulWidget {
final bool value;
final ValueChanged onChanged;
CustomSwitch({@required this.value, @required this.onChanged});
@override
_CustomSwitchState createState() => _CustomSwitchState(value);
}
class _CustomSwitchState extends State with SingleTickerProviderStateMixin {
bool value;
AnimationController _controller;
Animation _animation;
_CustomSwitchState(this.value);
@override
void initState() {
super.initState();
_controller = AnimationController(duration: Duration(milliseconds: 200), vsync: this);
_animation = Tween(begin: 0, end: 1).animate(_controller);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
value = !value;
widget.onChanged(value);
if (value) {
_controller.forward();
} else {
_controller.reverse();
}
},
child: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Transform.translate(
offset: Offset(20 * _animation.value - 20, 0),
child: CustomPaint(
painter: CustomSwitchPainter(value),
size: Size(70, 40),
),
);
},
),
);
}
}
3. 創建遊戲
Canvas可以用於創建跨平台的2D遊戲。例如,我們可以使用Canvas創建一個簡單的飛行射擊遊戲。
class Bullet {
Rect rect;
Bullet(this.rect);
}
class Enemy {
Rect rect;
double speed;
Enemy(this.rect, this.speed);
}
class GamePainter extends CustomPainter {
List bullets = [];
List enemies = [];
int score = 0;
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = Colors.red
..style = PaintingStyle.fill;
for (Bullet bullet in bullets) {
canvas.drawRect(bullet.rect, paint);
bullet.rect = bullet.rect.translate(0, -5);
}
paint.color = Colors.green;
for (Enemy enemy in enemies) {
canvas.drawRect(enemy.rect, paint);
enemy.rect = enemy.rect.translate(0, enemy.speed);
}
List bulletsToDelete = [];
List enemiesToDelete = [];
for (Bullet bullet in bullets) {
if (bullet.rect.top < 0) {
bulletsToDelete.add(bullet);
continue;
}
for (Enemy enemy in enemies) {
if (bullet.rect.overlaps(enemy.rect)) {
bulletsToDelete.add(bullet);
enemiesToDelete.add(enemy);
score++;
}
}
}
for (Bullet bullet in bulletsToDelete) {
bullets.remove(bullet);
}
for (Enemy enemy in enemiesToDelete) {
enemies.remove(enemy);
}
if (Random().nextInt(100) _GameState();
}
class _GameState extends State {
GlobalKey _key = GlobalKey();
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanUpdate: (details) {
RenderBox renderBox = _key.currentContext.findRenderObject();
Offset localPosition = renderBox.globalToLocal(details.globalPosition);
List bulletsToAdd = [];
bulletsToAdd.add(Bullet(Rect.fromLTWH(localPosition.dx - 3, localPosition.dy - 20, 6, 20)));
setState(() {
bulletsToAdd.forEach((bullet) => bullets.add(bullet));
});
},
child: CustomPaint(
painter: GamePainter(),
key: _key,
),
);
}
}
原創文章,作者:PSOFM,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/370647.html
微信掃一掃
支付寶掃一掃