Java 如何通过路径设置圆的动画?颤振

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(

首先,看我的问题有很多; 我想通过startClickPosition和endPosition创建一个贝塞尔路径,并绘制一个与其匹配的圆。 在这些代码中,我使用了_path.computeMetrics(),并获得了一个PathMetrics,然后我使用pms.elementAt(0)来获得PathMetrics,但我发现其中有一个错误,即pms.length为0。这是我的代码:

  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;
  }
}