canvas.dart 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. import 'dart:ui' as ui;
  2. import 'package:fis_measure/values/colors.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:path_drawing/path_drawing.dart';
  5. extension MeasureCanvasExt on Canvas {
  6. static String? _fontFamily;
  7. /// 设置字体
  8. static void setFontFamily(String? val) {
  9. _fontFamily = val;
  10. }
  11. /// 绘制文本
  12. ///
  13. /// [text] 文本内容
  14. ///
  15. /// [offset] 位置
  16. ///
  17. /// [style] 文字样式
  18. void drawText(
  19. String text,
  20. ui.Offset offset, {
  21. TextStyle? style,
  22. }) {
  23. var displayStyle = style;
  24. if (displayStyle != null) {
  25. if (displayStyle.fontFamily == null) {
  26. displayStyle = displayStyle.copyWith(fontFamily: _fontFamily);
  27. }
  28. }
  29. var textPainter = TextPainter(
  30. text: TextSpan(
  31. text: text,
  32. style: displayStyle,
  33. ),
  34. textAlign: ui.TextAlign.start,
  35. textDirection: TextDirection.ltr,
  36. );
  37. textPainter.layout();
  38. textPainter.paint(this, offset);
  39. }
  40. /// 绘制文本段落
  41. ///
  42. /// [text] 文本内容
  43. ///
  44. /// [offset] 位置
  45. ///
  46. /// [width] 限制长度
  47. ///
  48. /// [style] 文字样式
  49. ///
  50. /// [maxLines] 最大行数
  51. void drawTextParagraph(
  52. String text,
  53. ui.Offset offset,
  54. double width, {
  55. ui.TextStyle? style,
  56. int maxLines = 1,
  57. }) {
  58. var pb = ui.ParagraphBuilder(
  59. ui.ParagraphStyle(
  60. textAlign: TextAlign.left,
  61. textDirection: ui.TextDirection.ltr,
  62. maxLines: maxLines,
  63. ),
  64. );
  65. if (style != null) {
  66. pb.pushStyle(style);
  67. }
  68. pb.addText(text);
  69. final paragraph = pb.build()..layout(ui.ParagraphConstraints(width: width));
  70. drawParagraph(paragraph, offset);
  71. }
  72. /// 画虚线
  73. ///
  74. /// [p1] 第一个点
  75. ///
  76. /// [p2] 第二个点
  77. ///
  78. /// [dashWidth] 虚线点长度
  79. ///
  80. /// [spaceWidth] 虚线点间隔长度
  81. ///
  82. /// [paint] 画笔
  83. void drawDashLine(
  84. Offset p1,
  85. Offset p2,
  86. double dashWidth,
  87. double spaceWidth,
  88. Paint paint,
  89. ) {
  90. final path = Path()
  91. ..moveTo(p1.dx, p1.dy)
  92. ..lineTo(p2.dx, p2.dy);
  93. drawPath(
  94. dashPath(
  95. path,
  96. dashArray: CircularIntervalList<double>([dashWidth, spaceWidth]),
  97. ),
  98. paint,
  99. );
  100. }
  101. // 画实线连线
  102. void drawLine(
  103. Offset p1,
  104. Offset p2,
  105. Paint paint,
  106. ) {
  107. final path = Path()
  108. ..moveTo(p1.dx, p1.dy)
  109. ..lineTo(p2.dx, p2.dy);
  110. drawPath(path, paint);
  111. }
  112. /// 画虚线贝塞尔曲线
  113. /// [p1] 第一个点
  114. /// [p2] 第二个点
  115. /// [dashWidth] 虚线点长度
  116. /// [spaceWidth] 虚线点间隔长度
  117. /// [paint] 画笔
  118. /// [c1] 第一个控制点
  119. /// [c2] 第二个控制点
  120. void drawDashBezierLine(
  121. Offset p1,
  122. Offset p2,
  123. double dashWidth,
  124. double spaceWidth,
  125. Paint paint, {
  126. Offset? c1,
  127. Offset? c2,
  128. }) {
  129. final path = Path()
  130. ..moveTo(p1.dx, p1.dy)
  131. ..cubicTo(
  132. c1?.dx ?? p1.dx,
  133. c1?.dy ?? p1.dy,
  134. c2?.dx ?? p2.dx,
  135. c2?.dy ?? p2.dy,
  136. p2.dx,
  137. p2.dy,
  138. );
  139. drawPath(
  140. dashPath(
  141. path,
  142. dashArray: CircularIntervalList<double>([dashWidth, spaceWidth]),
  143. ),
  144. paint,
  145. );
  146. }
  147. /// 画虚线框
  148. ///
  149. /// [p1] 起始顶点
  150. ///
  151. /// [p2] 结束顶点
  152. ///
  153. /// [dashWidth] 虚线点长度
  154. ///
  155. /// [spaceWidth] 虚线点间隔长度
  156. ///
  157. /// [paint] 画笔
  158. void drawDashRect(
  159. Offset p1,
  160. Offset p2,
  161. double dashWidth,
  162. double spaceWidth,
  163. Paint paint,
  164. ) {
  165. final path = Path()
  166. ..moveTo(p1.dx, p1.dy)
  167. ..lineTo(p2.dx, p1.dy)
  168. ..lineTo(p2.dx, p2.dy)
  169. ..lineTo(p1.dx, p2.dy)
  170. ..close();
  171. drawPath(
  172. dashPath(
  173. path,
  174. dashArray: CircularIntervalList<double>([dashWidth, spaceWidth]),
  175. ),
  176. paint,
  177. );
  178. }
  179. /// 画点集连线
  180. /// [points] 点集
  181. /// [paint] 画笔
  182. void drawPointsLine(List<Offset> points, Paint paint) {
  183. final path = Path();
  184. for (var i = 0; i < points.length; i++) {
  185. if (i == 0) {
  186. path.moveTo(points[i].dx, points[i].dy);
  187. } else {
  188. path.lineTo(points[i].dx, points[i].dy);
  189. }
  190. }
  191. drawPath(path, paint);
  192. }
  193. /// 画点集虚线连线
  194. /// [points] 点集
  195. /// [dashWidth] 虚线点长度
  196. /// [spaceWidth] 虚线点间隔长度
  197. /// [paint] 画笔
  198. /// [close] 是否闭合
  199. void drawDashPointsLine(
  200. List<Offset> points,
  201. double dashWidth,
  202. double spaceWidth,
  203. Paint paint, {
  204. bool close = false,
  205. }) {
  206. final path = Path();
  207. for (var i = 0; i < points.length; i++) {
  208. if (i == 0) {
  209. path.moveTo(points[i].dx, points[i].dy);
  210. } else {
  211. path.lineTo(points[i].dx, points[i].dy);
  212. }
  213. }
  214. if (close) {
  215. path.close();
  216. }
  217. drawPath(
  218. dashPath(
  219. path,
  220. dashArray: CircularIntervalList<double>([dashWidth, spaceWidth]),
  221. ),
  222. paint,
  223. );
  224. }
  225. static final Paint _vertexPaint = Paint()
  226. ..strokeWidth = 1
  227. ..style = PaintingStyle.stroke
  228. ..isAntiAlias = true;
  229. /// 画顶点
  230. ///
  231. /// [offset] 位置
  232. ///
  233. /// [size] 尺寸
  234. ///
  235. /// [active] 是否活动
  236. void drawVertex(
  237. Offset offset,
  238. double size, {
  239. bool active = false,
  240. }) {
  241. final radius = size / 2.0;
  242. double x = offset.dx, y = offset.dy;
  243. save();
  244. final path = Path();
  245. // top_left -> bottom_right
  246. path.moveTo(x - radius, y - radius);
  247. path.lineTo(x + radius, y + radius);
  248. // top_right -> bottom_left
  249. path.moveTo(x + radius, y - radius);
  250. path.lineTo(x - radius, y + radius);
  251. _vertexPaint.color =
  252. active ? MeasureColors.ActiveCaliper : MeasureColors.ActivePrimary;
  253. drawPath(path, _vertexPaint);
  254. restore();
  255. }
  256. /// 画十字顶点
  257. ///
  258. /// [offset] 位置
  259. ///
  260. /// [size] 尺寸
  261. ///
  262. /// [active] 是否活动
  263. void drawCrossVertex(
  264. Offset offset,
  265. double size, {
  266. bool active = false,
  267. }) {
  268. final radius = size / 2.0;
  269. double x = offset.dx, y = offset.dy;
  270. save();
  271. final path = Path();
  272. // left -> right
  273. path.moveTo(x - radius, y);
  274. path.lineTo(x + radius, y);
  275. // top -> bottom
  276. path.moveTo(x, y - radius);
  277. path.lineTo(x, y + radius);
  278. _vertexPaint.color =
  279. active ? MeasureColors.ActiveCaliper : MeasureColors.ActivePrimary;
  280. drawPath(path, _vertexPaint..isAntiAlias = false);
  281. restore();
  282. }
  283. static final Paint _markPaint = Paint()
  284. ..strokeWidth = 1
  285. ..style = PaintingStyle.stroke
  286. ..isAntiAlias = false;
  287. ///绘制短横标记
  288. ///ifHorizontal true:横向标记 false:纵向标记
  289. void drawMark(
  290. Offset offset,
  291. double size, {
  292. bool active = false,
  293. bool ifHorizontal = true,
  294. }) {
  295. final radius = size / 3.0;
  296. double x = offset.dx, y = offset.dy;
  297. save();
  298. final path = Path();
  299. // top_left -> bottom_right
  300. if (ifHorizontal) {
  301. path.moveTo(x - radius, y);
  302. path.lineTo(x + radius, y);
  303. } else {
  304. path.moveTo(x, y - radius);
  305. path.lineTo(x, y + radius);
  306. }
  307. _markPaint.color =
  308. active ? MeasureColors.ActiveCaliper : MeasureColors.ActivePrimary;
  309. drawPath(path, _markPaint);
  310. restore();
  311. }
  312. }