gpt4 book ai didi

android - 为什么我在 Flutter AnimatedChecked 中得到了这一点? (自定义油漆)

转载 作者:行者123 更新时间:2023-12-01 16:11:38 24 4
gpt4 key购买 nike

免责声明 :

  • Flutter Beta - 1.19
  • Chrome 上的 Flutter Web

  • 向所有 Flutter 开发人员问好 :)
    我得到了一个动画检查小部件的解决方案(最初由: Raul Mateo ),我已经改进了它的行为和外观。
    但我不是 CustomPaint 专家,所以我不知道在下面的代码中,为什么我在选中线的转弯处得到那个绿点:
    漏洞
    enter image description here
    代码
    import 'package:flutter/material.dart';
    import 'package:angles/angles.dart';
    import 'dart:math';
    import 'dart:core';

    class AnimatedCheck extends StatefulWidget {
    final double size;
    final Color color;
    final double strokeWidth;
    final VoidCallback onComplete;

    const AnimatedCheck({
    this.size = 80.0,
    this.onComplete,
    this.strokeWidth = 2.5,
    this.color = Colors.green,
    });

    @override
    _AnimatedCheckState createState() => _AnimatedCheckState();
    }

    class _AnimatedCheckState extends State<AnimatedCheck> with SingleTickerProviderStateMixin {
    AnimationController _controller;
    Animation<double> curve;
    bool completed = false;

    @override
    void initState() {
    super.initState();
    _controller = AnimationController(duration: Duration(seconds: 2), vsync: this);
    curve = CurvedAnimation(parent: _controller, curve: Curves.decelerate);

    _controller.addListener(() {
    if (_controller.status == AnimationStatus.completed && widget.onComplete != null) {
    widget.onComplete();
    }
    if (_controller.status == AnimationStatus.completed) {
    completed = true;
    }
    setState(() {});
    });
    _controller.forward();
    }

    @override
    Widget build(BuildContext context) {
    return Stack(
    alignment: Alignment.center,
    fit: StackFit.passthrough,
    children: [
    AnimatedContainer(
    duration: const Duration(milliseconds: 250),
    height: widget.size,
    width: widget.size,
    decoration: BoxDecoration(
    shape: BoxShape.circle,
    color: Colors.transparent,
    border: Border.all(
    width: widget.strokeWidth,
    color: completed ? widget.color : widget.color.withOpacity(.05),
    ),
    ),
    ),
    Container(
    height: widget.size - widget.strokeWidth,
    width: widget.size - widget.strokeWidth,
    child: CustomPaint(
    painter: CheckPainter(
    value: curve.value,
    color: widget.color,
    strokeWidth: widget.strokeWidth,
    ),
    ),
    ),
    ],
    );
    }

    @override
    void dispose() {
    _controller.dispose();
    super.dispose();
    }
    }

    class CheckPainter extends CustomPainter {
    Paint _paint;
    double value;
    Color color;
    double strokeWidth;

    double _length;
    double _offset;
    double _secondOffset;
    double _startingAngle;

    CheckPainter({
    this.value,
    this.color,
    this.strokeWidth,
    }) {
    _paint = Paint()
    ..color = color
    ..strokeWidth = strokeWidth
    ..strokeCap = StrokeCap.round
    ..style = PaintingStyle.stroke;
    assert(value != null);

    _length = 60;
    _offset = 0;
    _startingAngle = 205;
    }

    @override
    void paint(Canvas canvas, Size size) {
    // Background canvas
    var rect = Offset(0, 0) & size;
    _paint.color = color.withOpacity(0);

    double line1x1 = size.width / 2 + size.width * cos(Angle.fromDegrees(_startingAngle).radians) * .5;
    double line1y1 = size.height / 2 + size.height * sin(Angle.fromDegrees(_startingAngle).radians) * .5;
    double line1x2 = size.width * .45;
    double line1y2 = size.height * .65;

    double line2x1 = size.width / 2 + size.width * cos(Angle.fromDegrees(320).radians) * .35;
    double line2y1 = size.height / 2 + size.height * sin(Angle.fromDegrees(320).radians) * .35;

    canvas.drawArc(rect, Angle.fromDegrees(_startingAngle).radians, Angle.fromDegrees(360).radians, false, _paint);
    canvas.drawLine(Offset(line1x1, line1y1), Offset(line1x2, line1y2), _paint);
    canvas.drawLine(Offset(line2x1, line2y1), Offset(line1x2, line1y2), _paint);

    // animation painter

    double circleValue, checkValue;
    if (value < .5) {
    checkValue = 0;
    circleValue = value / .5;
    } else {
    checkValue = (value - .5) / .5;
    circleValue = 1;
    }

    _paint.color = color;
    double firstAngle = _startingAngle + 360 * circleValue;
    double line1Value = 0, line2Value = 0;

    canvas.drawArc(rect, Angle.fromDegrees(firstAngle).radians,
    Angle.fromDegrees(getSecondAngle(firstAngle, _length, _startingAngle + 360)).radians, false, _paint);

    if (circleValue >= 1) {
    if (checkValue < .5) {
    line2Value = 0;
    line1Value = checkValue / .5;
    } else {
    line2Value = (checkValue - .55) / .55;
    line1Value = .75;
    }
    }

    double auxLine1x1 = (line1x2 - line1x1) * getMin(line1Value, .8);
    double auxLine1y1 = (((auxLine1x1) - line1x1) / (line1x2 - line1x1)) * (line1y2 - line1y1) + line1y1;

    if (_offset < 60) {
    auxLine1x1 = line1x1;
    auxLine1y1 = line1y1;
    }

    double auxLine1x2 = auxLine1x1 + _offset / 2;
    double auxLine1y2 = (((auxLine1x1 + _offset / 2) - line1x1) / (line1x2 - line1x1)) * (line1y2 - line1y1) + line1y1;

    if (checkIfPointHasCrossedLine(
    Offset(line1x2, line1y2), Offset(line2x1, line2y1), Offset(auxLine1x2, auxLine1y2))) {
    auxLine1x2 = line1x2;
    auxLine1y2 = line1y2;
    }

    if (_offset > 0) {
    canvas.drawLine(Offset(auxLine1x1, auxLine1y1), Offset(auxLine1x2, auxLine1y2), _paint);
    }

    // SECOND LINE

    double auxLine2x1 = (line2x1 - line1x2) * line2Value;
    double auxLine2y1 =
    ((((line2x1 - line1x2) * line2Value) - line1x2) / (line2x1 - line1x2)) * (line2y1 - line1y2) + line1y2;

    if (checkIfPointHasCrossedLine(
    Offset(line1x1, line1y1), Offset(line1x2, line1y2), Offset(auxLine2x1, auxLine2y1))) {
    auxLine2x1 = line1x2;
    auxLine2y1 = line1y2;
    }
    if (line2Value > 0) {
    canvas.drawLine(
    Offset(auxLine2x1, auxLine2y1),
    Offset(
    (line2x1 - line1x2) * line2Value + _offset * .75,
    ((((line2x1 - line1x2) * line2Value + _offset * .75) - line1x2) / (line2x1 - line1x2)) *
    (line2y1 - line1y2) +
    line1y2),
    _paint);
    }
    }

    double getMax(double x, double y) {
    return (x > y) ? x : y;
    }

    double getMin(double x, double y) {
    return (x > y) ? y : x;
    }

    bool checkIfPointHasCrossedLine(Offset a, Offset b, Offset point) {
    return ((b.dx - a.dx) * (point.dy - a.dy) - (b.dy - a.dy) * (point.dx - a.dx)) > 0;
    }

    double getSecondAngle(double angle, double plus, double max) {
    if (angle + plus > max) {
    _offset = angle + plus - max;
    return max - angle;
    } else {
    _offset = 0;
    return plus;
    }
    }

    @override
    bool shouldRepaint(CheckPainter old) {
    return old.value != value;
    }
    }

    最佳答案

    好像这和drawArc的web实现有关,下面的代码在ios上什么也没画,而是在web上画了一个点:

     canvas.drawArc(rect, 0, 0, false, _paint);
    您可以尝试有条件地绘制圆弧
        if (circleValue < 1)
    canvas.drawArc(
    rect,
    Angle.fromDegrees(firstAngle).radians,
    Angle.fromDegrees(
    getSecondAngle(firstAngle, _length, _startingAngle + 360))
    .radians,
    false,
    _paint);
    但首先你想移动 _offset更新自 getSecondAngle(...)到它自己的功能,因为它是两个独立的关注点
      double getUpdatedOffset(double angle, double plus, double max) =>
    angle + plus > max ? angle + plus - max : 0;
    并在条件 drawArc 之后调用它
        _offset = getUpdatedOffset(firstAngle, _length, _startingAngle + 360);
    完整更新的代码:
    import 'package:flutter/material.dart';
    import 'package:angles/angles.dart';
    import 'dart:math';
    import 'dart:core';

    class AnimatedCheck extends StatefulWidget {
    final double size;
    final Color color;
    final double strokeWidth;
    final VoidCallback onComplete;

    const AnimatedCheck({
    this.size = 80.0,
    this.onComplete,
    this.strokeWidth = 2.5,
    this.color = Colors.green,
    });

    @override
    _AnimatedCheckState createState() => _AnimatedCheckState();
    }

    class _AnimatedCheckState extends State<AnimatedCheck>
    with SingleTickerProviderStateMixin {
    AnimationController _controller;
    Animation<double> curve;
    bool completed = false;

    @override
    void initState() {
    super.initState();
    _controller =
    AnimationController(duration: Duration(seconds: 2), vsync: this);
    curve = CurvedAnimation(parent: _controller, curve: Curves.decelerate);

    _controller.addListener(() {
    if (_controller.status == AnimationStatus.completed &&
    widget.onComplete != null) {
    widget.onComplete();
    }
    if (_controller.status == AnimationStatus.completed) {
    completed = true;
    }
    setState(() {});
    });
    _controller.forward();
    }

    @override
    Widget build(BuildContext context) {
    return Stack(
    alignment: Alignment.center,
    fit: StackFit.passthrough,
    children: [
    AnimatedContainer(
    duration: const Duration(milliseconds: 250),
    height: widget.size,
    width: widget.size,
    decoration: BoxDecoration(
    shape: BoxShape.circle,
    color: Colors.transparent,
    border: Border.all(
    width: widget.strokeWidth,
    color: completed ? widget.color : widget.color.withOpacity(.05),
    ),
    ),
    ),
    Container(
    height: widget.size - widget.strokeWidth,
    width: widget.size - widget.strokeWidth,
    child: CustomPaint(
    painter: CheckPainter(
    value: curve.value,
    color: widget.color,
    strokeWidth: widget.strokeWidth,
    ),
    ),
    ),
    ],
    );
    }

    @override
    void dispose() {
    _controller.dispose();
    super.dispose();
    }
    }

    class CheckPainter extends CustomPainter {
    Paint _paint;
    double value;
    Color color;
    double strokeWidth;

    double _length;
    double _offset;
    double _secondOffset;
    double _startingAngle;

    CheckPainter({
    this.value,
    this.color,
    this.strokeWidth,
    }) {
    _paint = Paint()
    ..color = color
    ..strokeWidth = strokeWidth
    ..strokeCap = StrokeCap.round
    ..style = PaintingStyle.stroke;
    assert(value != null);

    _length = 60;
    _offset = 0;
    _startingAngle = 205;
    }

    @override
    void paint(Canvas canvas, Size size) {
    // Background canvas
    var rect = Offset(0, 0) & size;
    _paint.color = color.withOpacity(0);

    double line1x1 = size.width / 2 +
    size.width * cos(Angle.fromDegrees(_startingAngle).radians) * .5;
    double line1y1 = size.height / 2 +
    size.height * sin(Angle.fromDegrees(_startingAngle).radians) * .5;
    double line1x2 = size.width * .45;
    double line1y2 = size.height * .65;

    double line2x1 =
    size.width / 2 + size.width * cos(Angle.fromDegrees(320).radians) * .35;
    double line2y1 = size.height / 2 +
    size.height * sin(Angle.fromDegrees(320).radians) * .35;

    canvas.drawArc(rect, Angle.fromDegrees(_startingAngle).radians,
    Angle.fromDegrees(360).radians, false, _paint);
    canvas.drawLine(Offset(line1x1, line1y1), Offset(line1x2, line1y2), _paint);
    canvas.drawLine(Offset(line2x1, line2y1), Offset(line1x2, line1y2), _paint);

    // animation painter

    double circleValue, checkValue;
    if (value < .5) {
    checkValue = 0;
    circleValue = value / .5;
    } else {
    checkValue = (value - .5) / .5;
    circleValue = 1;
    }

    _paint.color = color;
    double firstAngle = _startingAngle + 360 * circleValue;
    double line1Value = 0, line2Value = 0;

    if (circleValue < 1)
    canvas.drawArc(
    rect,
    Angle.fromDegrees(firstAngle).radians,
    Angle.fromDegrees(
    getSecondAngle(firstAngle, _length, _startingAngle + 360))
    .radians,
    false,
    _paint);

    _offset = getUpdatedOffset(firstAngle, _length, _startingAngle + 360);

    if (circleValue >= 1) {
    if (checkValue < .5) {
    line2Value = 0;
    line1Value = checkValue / .5;
    } else {
    line2Value = (checkValue - .55) / .55;
    line1Value = .75;
    }
    }

    double auxLine1x1 = (line1x2 - line1x1) * getMin(line1Value, .8);
    double auxLine1y1 =
    (((auxLine1x1) - line1x1) / (line1x2 - line1x1)) * (line1y2 - line1y1) +
    line1y1;

    if (_offset < 60) {
    auxLine1x1 = line1x1;
    auxLine1y1 = line1y1;
    }

    double auxLine1x2 = auxLine1x1 + _offset / 2;
    double auxLine1y2 =
    (((auxLine1x1 + _offset / 2) - line1x1) / (line1x2 - line1x1)) *
    (line1y2 - line1y1) +
    line1y1;

    if (checkIfPointHasCrossedLine(Offset(line1x2, line1y2),
    Offset(line2x1, line2y1), Offset(auxLine1x2, auxLine1y2))) {
    auxLine1x2 = line1x2;
    auxLine1y2 = line1y2;
    }

    if (_offset > 0) {
    canvas.drawLine(Offset(auxLine1x1, auxLine1y1),
    Offset(auxLine1x2, auxLine1y2), _paint);
    }

    // SECOND LINE

    double auxLine2x1 = (line2x1 - line1x2) * line2Value;
    double auxLine2y1 =
    ((((line2x1 - line1x2) * line2Value) - line1x2) / (line2x1 - line1x2)) *
    (line2y1 - line1y2) +
    line1y2;

    if (checkIfPointHasCrossedLine(Offset(line1x1, line1y1),
    Offset(line1x2, line1y2), Offset(auxLine2x1, auxLine2y1))) {
    auxLine2x1 = line1x2;
    auxLine2y1 = line1y2;
    }
    if (line2Value > 0) {
    canvas.drawLine(
    Offset(auxLine2x1, auxLine2y1),
    Offset(
    (line2x1 - line1x2) * line2Value + _offset * .75,
    ((((line2x1 - line1x2) * line2Value + _offset * .75) - line1x2) /
    (line2x1 - line1x2)) *
    (line2y1 - line1y2) +
    line1y2),
    _paint);
    }
    }

    double getMax(double x, double y) {
    return (x > y) ? x : y;
    }

    double getMin(double x, double y) {
    return (x > y) ? y : x;
    }

    bool checkIfPointHasCrossedLine(Offset a, Offset b, Offset point) {
    return ((b.dx - a.dx) * (point.dy - a.dy) -
    (b.dy - a.dy) * (point.dx - a.dx)) >
    0;
    }

    double getSecondAngle(double angle, double plus, double max) =>
    angle + plus > max ? max - angle : plus;

    double getUpdatedOffset(double angle, double plus, double max) =>
    angle + plus > max ? angle + plus - max : 0;

    @override
    bool shouldRepaint(CheckPainter old) {
    return old.value != value;
    }
    }

    关于android - 为什么我在 Flutter AnimatedChecked 中得到了这一点? (自定义油漆),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62986605/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com