Flutter 画笔(Paint)、绘制直线(drawLine)

@override

bool shouldRepaint(CustomPainter oldDelegate) => true;

}

class MyPainter extends CustomPainter {

@override

void paint(Canvas canvas, Size size) {

//画背景

var paint = Paint()

…isAntiAlias = false

…strokeWidth=30.0

…color = Colors.red;

canvas.drawLine(Offset(50.0, 50.0), Offset(100.0,70.0), paint…strokeCap);

}

//在实际场景中正确利用此回调可以避免重绘开销,本示例我们简单的返回true

@override

bool shouldRepaint(CustomPainter oldDelegate) => true;

}

isAntiAlias=true(消除锯齿)

    

class MyPainter extends CustomPainter {

@override

void paint(Canvas canvas, Size size) {

//画背景

var paint = Paint()

…isAntiAlias = true

…strokeWidth=30.0

…color = Colors.red;

canvas.drawLine(Offset(50.0, 50.0), Offset(100.0,60.0), paint…strokeCap);

}

//在实际场景中正确利用此回调可以避免重绘开销,本示例我们简单的返回true

@override

bool shouldRepaint(CustomPainter oldDelegate) => true;

}

class MyPainter extends CustomPainter {

@override

void paint(Canvas canvas, Size size) {

//画背景

var paint = Paint()

…isAntiAlias = true

…strokeWidth=30.0

…color = Colors.red;

canvas.drawLine(Offset(50.0, 50.0), Offset(100.0,70.0), paint…strokeCap);

}

//在实际场景中正确利用此回调可以避免重绘开销,本示例我们简单的返回true

@override

bool shouldRepaint(CustomPainter oldDelegate) => true;

}

strokeWidth(画笔宽度)

class MyPainter extends CustomPainter {

@override

void paint(Canvas canvas, Size size) {

//画背景

var paint = Paint()

…isAntiAlias = true

…color = Colors.red;

canvas.drawLine(Offset(50.0, 46.0), Offset(200.0,46.0), paint…strokeCap…strokeWidth=4.0);

canvas.drawLine(Offset(50.0, 60.0), Offset(200.0,60.0), paint…strokeCap…strokeWidth=8.0);

canvas.drawLine(Offset(50.0, 80.0), Offset(200.0,80.0), paint…strokeCap…strokeWidth=16.0);

canvas.drawLine(Offset(50.0, 110.0), Offset(200.0,110.0), paint…strokeCap…strokeWidth=20.0);

}

//在实际场景中正确利用此回调可以避免重绘开销,本示例我们简单的返回true

@override

bool shouldRepaint(CustomPainter oldDelegate) => true;

}

strokeCap(buff、round、square)

### Flutter 时钟绘制:十二点位置位于正上方的实现方法 在 Flutter 中,使用 `CustomPaint` 和 `Canvas` 进行自定义绘图时,通常会遇到坐标系的问题。默认情况下,Flutter 的 `Canvas` 坐标系是以左上角为原点 `(0, 0)`,向右为 X 轴正方向,向下为 Y 轴正方向。然而,在绘制时钟时,我们希望以圆心为中心,并且让时钟的十二点钟方向指向屏幕的正上方。 #### 解决方案 要实现这一目标,可以通过以下步骤完成: 1. **调整角度偏移量** 在计算指针的角度时,默认的起点是从 X 轴正方向(3 点钟方向)开始顺时针旋转。为了让十二点钟方向对应到正上方,需要对所有的角度加上 `-π/2` 的偏移量[^1]。 2. **转换角度单位** 时间对应的小时、分钟和秒数需要转化为弧度值,再应用上述的偏移量。 3. **绘制指针** 使用三角函数 `cos` 和 `sin` 计算指针末端的坐标,并将其连接至圆心。 以下是完整的代码示例: ```dart import 'dart:ui'; import 'package:flutter/material.dart'; class ClockWidget extends StatefulWidget { @override _ClockWidgetState createState() => _ClockWidgetState(); } class _ClockWidgetState extends State<ClockWidget> { late DateTime now; @override void initState() { super.initState(); now = DateTime.now(); Timer.periodic(Duration(seconds: 1), (timer) { setState(() { now = DateTime.now(); // 更新时间为当前时间 }); }); } @override Widget build(BuildContext context) { return Center( child: SizedBox( width: 200, height: 200, child: CustomPaint(painter: ClockPainter(now)), ), ); } } class ClockPainter extends CustomPainter { final DateTime dateTime; ClockPainter(this.dateTime); @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); // 圆心 final radius = size.width / 2 - 10; // 表盘半径 // 设置画笔样式 final Paint circlePaint = Paint() ..color = Colors.black.withOpacity(0.5) ..style = PaintingStyle.stroke ..strokeWidth = 2; // 绘制表盘 canvas.drawCircle(center, radius, circlePaint); // 绘制时针、分针和秒针 drawHand(canvas, center, radius, calculateAngleInRadians(dateTime.hour.toDouble(), isHour: true)); drawHand(canvas, center, radius, calculateAngleInRadians(dateTime.minute.toDouble())); drawHand(canvas, center, radius, calculateAngleInRadians(dateTime.second.toDouble()), color: Colors.red); // 绘制中心的小圆点 canvas.drawCircle(center, 5, Paint()..color = Colors.black); } /// 计算角度(弧度) double calculateAngleInRadians(double value, {bool isHour = false}) { if (isHour) { value %= 12; // 小时取模 12 value += dateTime.minute / 60; // 加入分钟的影响 } else { value %= 60; // 分钟或秒取模 60 } return ((value / (isHour ? 12 : 60)) * 2 * pi) - (pi / 2); // 减去 π/2,使十二点朝上 } /// 绘制指针 void drawHand(Canvas canvas, Offset center, double radius, double angle, {Color? color}) { final handLengthFactor = color == Colors.red ? 0.9 : (color == null ? 0.5 : 0.7); // 不同颜色长度不同 final endX = center.dx + (radius * handLengthFactor * cos(angle)); final endY = center.dy + (radius * handLengthFactor * sin(angle)); canvas.drawLine(center, Offset(endX, endY), Paint() ..color = color ?? Colors.black ..strokeWidth = 2 ..style = PaintingStyle.stroke); } @override bool shouldRepaint(CustomPainter oldDelegate) => true; } ``` --- ### 关键点解析 1. **角度偏移处理** - 默认情况下,`drawArc()` 或者三角函数计算的角度均以 X 轴正方向为零点。 - 添加 `-π/2` 的偏移量后,使得原本从 3 点钟方向开始的角度变为从 12 点钟方向开始。 2. **动态更新时间** - 使用 `Timer.periodic` 每隔一秒钟刷新一次时间数据,并通过 `setState()` 触发界面重绘[^3]。 3. **指针长度控制** - 根据不同的指针类型(时针、分针、秒针),设定其长度比例分别为 `0.5`, `0.7`, 和 `0.9` 倍的半径。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值