Java 如何通过路径设置圆的动画?颤振
首先,看我的问题有很多; 我想通过startClickPosition和endPosition创建一个贝塞尔路径,并绘制一个与其匹配的圆。 在这些代码中,我使用了_path.computeMetrics(),并获得了一个PathMetrics,然后我使用pms.elementAt(0)来获得PathMetrics,但我发现其中有一个错误,即pms.length为0。这是我的代码:Java 如何通过路径设置圆的动画?颤振,java,android,flutter,dart,Java,Android,Flutter,Dart,首先,看我的问题有很多; 我想通过startClickPosition和endPosition创建一个贝塞尔路径,并绘制一个与其匹配的圆。 在这些代码中,我使用了_path.computeMetrics(),并获得了一个PathMetrics,然后我使用pms.elementAt(0)来获得PathMetrics,但我发现其中有一个错误,即pms.length为0。这是我的代码: Path getPath(){ Path path = Path(); path.moveTo(
Path getPath(){
Path path = Path();
path.moveTo(widget.startOffset.dx, widget.startOffset.dy);
// i'm ensure this 4 var got value and is right value,below this line.
double startX = widget.endOffset.dx / 2;
double startY = widget.startOffset.dy;
double endX = widget.endOffset.dx;
double endY = widget.endOffset.dy;
path.quadraticBezierTo(startX,startY,endX ,endY);
return path;
}
startAnimation(){
_path = getPath();
if(_path == null) print("path is null");
PathMetrics pms = _path.computeMetrics(forceClosed: false);
// here pms.length is always 0;
PathMetric pm = pms.elementAt(0);
double pathLen = pm.length;
_animation = Tween(begin: 0.0,end: pathLen).animate(_controller)
..addListener((){
setState(() {
_fraction = _animation.value;
print("fraction _____ $_fraction");
});
})
..addStatusListener((status){
if(status == AnimationStatus.completed){
_controller.stop();
}
});
_controller.forward();
}
(有很多。)
整个代码:
class ParabolaAnimation extends StatefulWidget{
Size screenSize;
Offset startOffset;
Offset endOffset;
ParabolaAnimation(this.startOffset,this.endOffset,this.screenSize);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return ParabolaAnimationState();
}
}
class ParabolaAnimationState extends State<ParabolaAnimation> with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
double _fraction = 0.0;
int _seconds = 3;
Path _path;
GlobalKey _key = GlobalKey();
@override
void initState() {
// TODO: implement initState
_controller = AnimationController(vsync: this,duration: Duration(seconds: _seconds));
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
WidgetsBinding.instance.addPostFrameCallback((_){
startAnimation();
});
return CustomPaint(
painter: PathPainter(_path, _fraction),
// child: Container(
// width: widget.screenSize.width,
// height: widget.screenSize.height,
// ),
);
}
startAnimation(){
_path = getPath();
print("path ${_path.toString()} ___ ");
if(_path == null) print("path is null");
PathMetrics pms = _path.computeMetrics(forceClosed: false);
if(pms.length == 0) return;
int plen = pms.length;
//only one path
PathMetric pm = pms.elementAt(0);
double pathLen = pm.length;
print("path len : $pathLen");
_animation = Tween(begin: 0.0,end: pathLen).animate(_controller)
..addListener((){
setState(() {
_fraction = _animation.value;
print("fraction _____ $_fraction");
});
})
..addStatusListener((status){
if(status == AnimationStatus.completed){
_controller.stop();
}
});
_controller.forward();
}
Path getPath(){
print("start offset ${widget.startOffset.toString()}");
print("end offset ${widget.endOffset.toString()}");
Path path = Path();
path.moveTo(widget.startOffset.dx, widget.startOffset.dy);
double startX = widget.endOffset.dx / 2;
double startY = widget.startOffset.dy;
double endX = widget.endOffset.dx;
double endY = widget.endOffset.dy;
path.quadraticBezierTo(startX,startY,endX ,endY);
return path;
}
}
class PathPainter extends CustomPainter{
double fraction;
Path _path;
List<Offset> _points = List();
PathPainter(this._path,this.fraction);
Paint circleP = Paint()
..color = Colors.orange
..style = PaintingStyle.fill;
@override
void paint(Canvas canvas, Size size) {
if(_path == null) return;
print("fraction paint _____ $fraction");
PathMetrics pms = _path.computeMetrics();
PathMetric pm = pms.elementAt(0);
double pathLen = pm.length;
double circleR = 10;
Offset circleCenterOffset;
Tangent t = pm.getTangentForOffset(fraction);// 圆心
circleCenterOffset = t.position;
print("circle center ${circleCenterOffset.dx} + ${circleCenterOffset.dy}");
canvas.drawCircle(circleCenterOffset, circleR, circleP);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
类抛物线动画扩展StatefulWidget{
屏幕大小;
偏置STARTOFSET;
偏移内偏移;
抛物线动画(this.startOffset,this.endOffset,this.screenSize);
@凌驾
状态createState(){
//TODO:实现createState
返回抛物线动画状态();
}
}
类ParabolaAnimationState使用SingleTickerProviderStateMixin扩展状态{
动画控制器_控制器;
动画(动画),;
双_分数=0.0;
整数秒=3;
路径(u路径),;
GlobalKey _key=GlobalKey();
@凌驾
void initState(){
//TODO:实现initState
_控制器=动画控制器(vsync:this,duration:duration(秒:_秒));
super.initState();
}
@凌驾
无效处置(){
//TODO:实现dispose
_controller.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
//TODO:实现构建
WidgetsBinding.instance.addPostFrameCallback((){
startAnimation();
});
返回自定义油漆(
画家:路径画家(_路径,_分数),
//子:容器(
//宽度:widget.screenSize.width,
//高度:widget.screenSize.height,
// ),
);
}
startAnimation(){
_path=getPath();
打印(“路径${{path.toString()}}}”;
如果(_path==null)打印(“路径为null”);
PathMetrics pms=_path.computeMetrics(forceClosed:false);
如果(pms.length==0)返回;
int plen=pms.长度;
//只有一条路
路径度量pm=pms.elementAt(0);
双路径长度=pm.length;
打印(“路径len:$pathLen”);
_动画=Tween(开始:0.0,结束:pathLen)。动画(\u控制器)
…addListener(){
设置状态(){
_分数=_animation.value;
打印(“分数”);
});
})
..addStatusListener((状态){
如果(状态==AnimationStatus.completed){
_controller.stop();
}
});
_controller.forward();
}
路径getPath(){
打印(“开始偏移量${widget.startOffset.toString()}”);
打印(“结束偏移量${widget.endOffset.toString()}”);
路径=路径();
moveTo(widget.startOffset.dx,widget.startOffset.dy);
double startX=widget.endOffset.dx/2;
double startY=widget.startOffset.dy;
double-endX=widget.endOffset.dx;
double-endY=widget.endOffset.dy;
二次方贝塞尔托路径(startX、startY、endX、endY);
返回路径;
}
}
类PathPainter扩展了CustomPainter{
双分数;
路径(u路径),;
列表_点=列表();
PathPainter(这个路径,这个分数);
绘制循环=绘制()
…颜色=颜色。橙色
..风格=绘画风格。填充;
@凌驾
空心油漆(帆布,尺寸){
if(_path==null)返回;
打印(“分数油漆”\uuuuuuuuuuuuuuuuuuuuu$fraction”);
PathMetrics pms=_path.computeMetrics();
路径度量pm=pms.elementAt(0);
双路径长度=pm.length;
双圈器=10;
偏移圆偏移;
切线t=pm.getTangentForOffset(分数);//圆心
circleCenterOffset=t位置;
打印(“圆心${circleCenterOffset.dx}+${circleCenterOffset.dy}”);
画布.画圈(圈、圈、圈、圈);
}
@凌驾
bool应重新绘制(自定义代理){
//TODO:实现应重新绘制
返回true;
}
}
类圆扩展StatefulWidget{
@凌驾
_CircleState createState();
}
类_CircleState使用SingleTickerProviderStateMixin扩展状态{
双_分数=0.0;
动画(动画),;
动画控制器_控制器;
@凌驾
void initState(){
super.initState();
_控制器=
AnimationController(持续时间:持续时间(毫秒:300),vsync:this);
_动画=Tween(开始:0.0,结束:1.0)。动画(\u控制器)
…addListener(){
设置状态(){
_分数=_animation.value;
});
});
_controller.forward();
}
@凌驾
小部件构建(构建上下文){
返回容器(
儿童:中心(
孩子:AspectRatio(
aspectRatio:1.0,
孩子:填充(
填充:常数边集全部(24.0),
孩子:定制油漆(
油漆工:电路油漆工(分数:_分数),
),
),
),
),
);
}
@凌驾
无效处置(){
_controller.dispose();
super.dispose();
}
}
类CirclePaint扩展了CustomPainter{
最终双分数;
var_电路图;
电路绘制者({this.fraction}){
_circlePaint=Paint()
…颜色=圆形
…风格=绘画风格笔划
..冲程宽度=12.0
..strokeCap=strokeCap.round;
}
@凌驾
空心油漆(帆布,尺寸){
var rect=偏移量(0.0,0.0)和大小;
画布.drawArc(rect,-pi/2,pi*2*分数,false,_circlePaint);
}
@凌驾
bool应重新喷漆(电路油漆工oldDelegate){
返回oldDelegate.fraction!=分数;
}
}
路径p=Path();p、 moveTo(100100);p、 二次贝塞尔托(100200200200);ui.PathMetrics metrics=p.computeMetrics(forceClosed:false);ui.PathMetric=metrics.first;打印('162.06173706054688=${metric.length}')代码>你在日志上看到了什么?@pskink谢谢你的回答,今天很忙,所以,我明天会检查一下,马上告诉你。祝你今天愉快。:)@pskink日志:162.06173706054688==162.06173706054688.s
class Circle extends StatefulWidget {
@override
_CircleState createState() => _CircleState();
}
class _CircleState extends State<Circle> with SingleTickerProviderStateMixin {
double _fraction = 0.0;
Animation<double> _animation;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller =
AnimationController(duration: Duration(milliseconds: 300), vsync: this);
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
..addListener(() {
setState(() {
_fraction = _animation.value;
});
});
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: AspectRatio(
aspectRatio: 1.0,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: CustomPaint(
painter: CirclePainter(fraction: _fraction),
),
),
),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
class CirclePainter extends CustomPainter {
final double fraction;
var _circlePaint;
CirclePainter({this.fraction}) {
_circlePaint = Paint()
..color = circleColor
..style = PaintingStyle.stroke
..strokeWidth = 12.0
..strokeCap = StrokeCap.round;
}
@override
void paint(Canvas canvas, Size size) {
var rect = Offset(0.0, 0.0) & size;
canvas.drawArc(rect, -pi / 2, pi * 2 * fraction, false, _circlePaint);
}
@override
bool shouldRepaint(CirclePainter oldDelegate) {
return oldDelegate.fraction != fraction;
}
}