https://iter01.com/503194.html
https://www.programminghunter.com/article/66202389391/
https://juejin.cn/post/7066707431971094542
https://blog.csdn.net/wangzhongshun/article/details/96110665
Path是flutter的路徑元件,可以透過這個來儲存要繪製的圖案。
Path有很多繪製路徑的方法,如
(一)、移動到某位置 moveTo
moveTo(x,y) 默認的點為(0,0),使用此方法會移動到(x,y)的位置上。
Path path=Path();
..moveTo(100,100); 移動到x軸100,y軸100的位置
(二)、畫線到某位置 lineTo
lineTo(x,y) 由移動的上一點,畫到下一點(x,y)的位置。
Path path=Path();
..moveTo(100,100); 移動到x軸100,y軸100的位置
..lineTo(100,100); 由上面x軸100,y軸100的位置,至x軸150,y軸150的路徑
(三)、畫貝茲曲線 quadraticBezierTo(從當前位置出發,以)
quadTo(float x1, float y1, float x2, float y2)
quadraticBezierTo(控制點x, 控制點y, 終點x,終點y);addRect(Rect.fromLTWH(矩形左邊距離,矩形上邊矩離,矩形寬度,矩形高度));
bool forceMoveTo 屬性為真或假,true的話會從最後一個位置連接一條線到那個弧線,false不會連接會重新開始一個新的弧線
addOval(Rect.fromLTWH(矩形左邊距離,矩形上邊矩離,矩形寬度,矩形高度));
addPolygon([ 第一點位置, 第二點位置, 第三點位置 ], false);
位置的寫法用Offset(x偏移量,y偏移量);
在使用Canvas畫布時,都需給予畫筆的屬性,Paint的設定方法如下:
Paint paint = Paint()
..color = Colors.blue //繪圖中使用的畫筆顏色
..strokeWidth = 3.0; //畫筆的寬度
..style = PaintingStyle.fill //繪畫風格,默認為填充 nono為不填充
..strokeCap = StrokeCap.round //畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒 false會有鋸齒
..blendMode = BlendMode.exclusion //顏色混合的方法
..colorFilter = ColorFilter.mode(Colors.blueAccent, BlendMode.exclusion) //顏色渲染模式
..maskFilter = MaskFilter.blur(BlurStyle.inner, 4.0) //模糊遮罩效果
..filterQuality = FilterQuality.high //顏色渲染模式時的品質
使用path.computeMetrics() 獲取到 PathMetrics 這個對象的列表,因為繪製的路徑可能有很多組,而透過.computeMetrics() 這個方法,可以將這些路徑存在一個列表中,可依順序讀取出來。
(1)length 為取出列表的長度(由幾個路徑圖形組成)
(2)取出path中的其中一個路徑
若是只有一個路徑可以透過single取出。
若是有很多路徑,要取出第一個可使用.first,要取出最後一個可使用.last。
若要取得其它特定第幾個的路徑,可用.elementAt(index)。
若要取得其它部份,因為.computeMetrics()的列表為iterate,因此要使用path.computeMetrics().toList()先轉成List,再用List的方法取出裡面的路徑。
如:path.computeMetrics().toList()[2]
(3)取出其中一個路徑後,可用.extractPath,節取這個路徑由某一個點到另一個點的路徑。如下:
extractPath(double start, double end, {bool startWithMoveTo = true})
(4).getTangentForOffset()
當用上面的path.computeMetrics().single或是其它屬性,取出某一個路徑後,可用.getTangentForOffset()來取出這個路徑某一個切點,再利用.position()。可以獲得這個切點的座標。
(1)繪製圓角方形
class ButtonPaint2 extends CustomPainter {
final Animation<double> animation;
final double buttonWidth;
final double buttonHeight;
Paint p = Paint()
..style = PaintingStyle.stroke
..color = Colors.red
..strokeWidth = 5;
ButtonPaint2({
required this.animation,
required this.buttonWidth,
required this.buttonHeight,
}) : super(repaint: animation);
@override
void paint(Canvas canvas, Size size) {
final Path path = new Path()
..moveTo(buttonWidth / 2, 0)
..relativeLineTo(buttonWidth / 2 - 16, 0)
..relativeArcToPoint(Offset(16, 16),radius: Radius.circular(16))
..relativeLineTo(0,buttonHeight-32)
..relativeArcToPoint(Offset(-16, 16),radius: Radius.circular(16))
..relativeLineTo(16-buttonWidth,0)
..relativeArcToPoint(Offset(-16, -16),radius: Radius.circular(16))
..relativeLineTo(0,32-buttonHeight)
..relativeArcToPoint(Offset(16, -16),radius: Radius.circular(16))
..close();
canvas.drawPath(path, p);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
throw UnimplementedError();
}
}
(2)透過pathMetric與動畫結合,製作緣路徑跑動的圓點
import 'package:flutter/material.dart';
import 'dart:ui';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller =
AnimationController(duration: Duration(seconds: 2), vsync: this);
// TODO
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget? child) {
return CustomPaint(
foregroundPainter: custompainter(_controller.value),
);
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_controller.reset();
_controller.forward();
},
),
);
}
}
class custompainter extends CustomPainter {
var tweenTime;
custompainter(this.tweenTime);
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..style = PaintingStyle.stroke
..color = Colors.blue
..strokeWidth = 4;
var path = Path();
path.moveTo(50, 500);
path.cubicTo(50, 200, 300, 400, 350, 150);
canvas.drawPath(path, paint);
PathMetrics pathMetrics = path.computeMetrics();
PathMetric pathMetric3 = path.computeMetrics().elementAt(0);
//透過getTangentForOffset取得path路徑上的資料
Tangent? location=pathMetric3.getTangentForOffset(pathMetric3.length*tweenTime);
if (location != null) {
print(location.position);
canvas.drawCircle(location.position, 5, paint);
}
paint.color = Colors.red;
for (PathMetric pathMetric in pathMetrics) {
Path extractPath = pathMetric.extractPath(
0.0,
pathMetric.length * tweenTime,
);
canvas.drawPath(extractPath, paint);
}
@override
bool shouldRepaint(oldDelegate) {
return oldDelegate != oldDelegate;
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
沒有留言:
張貼留言