颤动的弧度?

时间:2018-05-08 04:01:07

标签: dart flutter

我有一个Paint对象,我正在尝试使用canvas.drawArc来绘制弧度,但是这样做的唯一方法(至少根据我的研究)是使用Shader,但要从Shader对象获取Gradient,您必须使用Gradient.createShader(Rect rect),这需要一个矩形。我的问题是,有没有办法为Arc而不是Rectangle创建着色器?以下是我到目前为止的参考资料:

Paint paint = new Paint()
  ..color = bgColor
  ..strokeCap = StrokeCap.round
  ..strokeWidth = 3.0
  ..style = PaintingStyle.stroke
  ..shader = new Gradient.radial(size.width / 2.0, size.height / 2.0, size.height / 3.0, Colors.transparent, timerColor, TileMode.mirror).createShader(/* I don't have a rect object */);


canvas.drawArc(..., paint);

2 个答案:

答案 0 :(得分:4)

您需要的矩形实际上是一个正方形,您绘制的圆将适合该正方形。圆弧只是从那个圆圈中掠过这么多弧度的一片馅饼。使用Rect.fromCircle使用中心和半径创建此方块。然后在创建渐变和绘制圆弧时使用此正方形。

这是一个例子

import 'dart:math';

import 'package:flutter/material.dart';

class X1Painter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // create a bounding square, based on the centre and radius of the arc
    Rect rect = new Rect.fromCircle(
      center: new Offset(165.0, 55.0),
      radius: 180.0,
    );

    // a fancy rainbow gradient
    final Gradient gradient = new RadialGradient(
      colors: <Color>[
        Colors.green.withOpacity(1.0),
        Colors.green.withOpacity(0.3),
        Colors.yellow.withOpacity(0.2),
        Colors.red.withOpacity(0.1),
        Colors.red.withOpacity(0.0),
      ],
      stops: [
        0.0,
        0.5,
        0.7,
        0.9,
        1.0,
      ],
    );

    // create the Shader from the gradient and the bounding square
    final Paint paint = new Paint()..shader = gradient.createShader(rect);

    // and draw an arc
    canvas.drawArc(rect, pi / 4, pi * 3 / 4, true, paint);
  }

  @override
  bool shouldRepaint(X1Painter oldDelegate) {
    return true;
  }
}

class X1Demo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: const Text('Arcs etc')),
      body: new CustomPaint(
        painter: new X1Painter(),
      ),
    );
  }
}

void main() {
  runApp(
    new MaterialApp(
      theme: new ThemeData.dark(),
      home: new X1Demo(),
    ),
  );
}

答案 1 :(得分:1)

我的SweepGradient版本。

完整示例:

import 'dart:math' as math;

import 'package:flutter/material.dart';

class GradientArcPainterDemo extends StatefulWidget {
  const GradientArcPainterDemo({
    Key key,
  }) : super(key: key);

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

class GradientArcPainterDemoState extends State<GradientArcPainterDemo> {
  double _progress = 0.9;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(title: const Text('GradientArcPainter Demo')),
      body: GestureDetector(
        onTap: () {
          setState(() {
            _progress += 0.1;
          });
        },
        child: Center(
          child: SizedBox(
            width: 200.0,
            height: 200.0,
            child: CustomPaint(
              painter: GradientArcPainter(
                progress: _progress,
                startColor: Colors.blue,
                endColor: Colors.red,
                width: 8.0,
              ),
              child: Center(child: Text('$_progress')),
            ),
          ),
        ),
      ),
    );
  }
}

class GradientArcPainter extends CustomPainter {
  const GradientArcPainter({
    @required this.progress,
    @required this.startColor,
    @required this.endColor,
    @required this.width,
  })  : assert(progress != null),
        assert(startColor != null),
        assert(endColor != null),
        assert(width != null),
        super();

  final double progress;
  final Color startColor;
  final Color endColor;
  final double width;

  @override
  void paint(Canvas canvas, Size size) {
    final rect = new Rect.fromLTWH(0.0, 0.0, size.width, size.height);
    final gradient = new SweepGradient(
      startAngle: 3 * math.pi / 2,
      endAngle: 7 * math.pi / 2,
      tileMode: TileMode.repeated,
      colors: [startColor, endColor],
    );

    final paint = new Paint()
      ..shader = gradient.createShader(rect)
      ..strokeCap = StrokeCap.butt  // StrokeCap.round is not recommended.
      ..style = PaintingStyle.stroke
      ..strokeWidth = width;
    final center = new Offset(size.width / 2, size.height / 2);
    final radius = math.min(size.width / 2, size.height / 2) - (width / 2);
    final startAngle = -math.pi / 2;
    final sweepAngle = 2 * math.pi * progress;
    canvas.drawArc(new Rect.fromCircle(center: center, radius: radius),
        startAngle, sweepAngle, false, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

结果: