Flutter中如何实现线条的斜角截断?
问题描述
通过继承CustomPainter类绘制线条时,无法实现截图所示的斜角截断效果,现有代码如下,附当前效果与期望效果截图:
绘制代码
class StationPointPainter extends CustomPainter { StationPointPainter({}); @override void paint(Canvas canvas, Size size) { final strokeWidthThin = size.width * 0.07; Paint paintMain = Paint() ..style = PaintingStyle.stroke ..strokeWidth = strokeWidthThin ..color = constants.Colors.purpleMain; Paint paintPurpleThin = Paint() ..style = PaintingStyle.stroke ..strokeWidth = strokeWidthThin ..color = constants.Colors.purpleMain; Paint paintPurpleBold = Paint() ..style = PaintingStyle.stroke ..strokeWidth = size.width * 0.16 ..shader = ui.Gradient.linear( Offset(size.width * 0.54, size.height * 1.03), Offset( size.width / 2 + size.width * 0.3, size.height * 0.45, ), [ constants.Colors.red, constants.Colors.green ], [ 0.3, 0.6, ]); Paint paintGreen = Paint() ..style = PaintingStyle.stroke ..strokeWidth = strokeWidthThin ..color = constants.Colors.purpleMainDark.withOpacity(isClosed ? 0.5 : 1); Paint paintTransparent = Paint() ..style = PaintingStyle.stroke ..strokeWidth = size.width * 0.04 ..color = constants.Colors.purpleMainDark; final pathMain = Path() ..moveTo(size.width / 2, size.height * 1.05) ..lineTo(size.width / 2 - size.width * 0.3, size.height * 0.4) ..arcToPoint( Offset(size.width - size.width * 0.2, size.height * 0.8), clockwise: true, radius: const Radius.circular(0.9), ) ..lineTo(size.width / 2 + size.width * 0.3, size.height * 0.4); final pathGreen = Path() ..moveTo(size.width / 2 + size.width * 0.3, size.height * 0.4) ..lineTo(size.width / 2, size.height) ..arcToPoint( Offset(size.width - size.width * 0.22, size.height * 0.26), clockwise: true, radius: const Radius.circular(0.9), ); final pathPurpleThin = Path() ..moveTo(size.width / 2, size.height * 1.05) ..lineTo(size.width / 2 - size.width * 0.3, size.height * 0.4); final pathPurpleBold = Path() ..moveTo(size.width * 0.54, size.height * 1.03) ..lineTo(size.width / 2 + size.width * 0.3, size.height * 0.45); final pathTransparent = Path() ..moveTo(size.width * 0.44, size.height) ..lineTo(size.width * 0.58, size.height * 0.68); pathMain.close(); pathGreen.close(); pathPurpleThin.close(); pathTransparent.close(); if (!isClosed) { canvas.drawPath(pathMain, paintMain); canvas.drawPath(pathGreen, paintGreen); canvas.drawPath(pathPurpleThin, paintPurpleThin); canvas.drawPath(pathTransparent, paintTransparent); } canvas.drawPath(pathPurpleBold, paintPurpleBold); } @override bool shouldRepaint(CustomPainter oldDelegate) { return true; } }
布局代码
ClipPath( clipper: StationPointClipper(), child: Container( width: width, height: height, color: constants.Colors.purpleMainDark, child: CustomPaint( painter: StationPointPainter(), ), ), ),
当前效果

期望效果

解决方法
要实现斜角截断效果,不能用描边模式绘制粗线条,需改为填充闭合的梯形路径模拟斜角线条,具体修改如下:
修改画笔模式为填充
将paintPurpleBold的style从PaintingStyle.stroke改为PaintingStyle.fill,移除strokeWidth(填充模式无需该参数):Paint paintPurpleBold = Paint() ..style = PaintingStyle.fill ..shader = ui.Gradient.linear( Offset(size.width * 0.54, size.height * 1.03), Offset( size.width / 2 + size.width * 0.3, size.height * 0.45, ), [ constants.Colors.red, constants.Colors.green ], [ 0.3, 0.6, ]);构建梯形路径
基于原线条的起点、终点和宽度,计算梯形的四个顶点,绘制闭合路径:final boldStrokeWidth = size.width * 0.16; final startPoint = Offset(size.width * 0.54, size.height * 1.03); final endPoint = Offset(size.width / 2 + size.width * 0.3, size.height * 0.45); // 计算线条垂直方向的偏移向量 final dir = endPoint - startPoint; final perpDir = Offset(-dir.dy, dir.dx).normalized * (boldStrokeWidth / 2); // 斜角延伸长度,可按需调整以改变斜角尖锐度 final angleExtend = dir.normalized * (boldStrokeWidth / 2); final pathPurpleBold = Path() ..moveTo(startPoint - perpDir) ..lineTo(startPoint + perpDir) ..lineTo(endPoint + perpDir + angleExtend) ..lineTo(endPoint - perpDir + angleExtend) ..close();替换原绘制逻辑
用新的pathPurpleBold替换原直线路径,直接填充即可得到斜角截断的粗线条。
调整angleExtend的乘数可以改变斜角的长度与角度,匹配你的期望效果。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

