如何使用Flutter有效地创建字母跟踪应用程序?

时间:2019-05-21 10:03:13

标签: flutter flutter-layout flutter-animation

我正在尝试使用Flutter创建一个字母跟踪应用程序。以下是我打算实现和迄今为止已经实现的屏幕截图。

打算实现: https://imgur.com/3KfWFA7

使用以下提供的代码实现: https://imgur.com/6LTcITG

import 'package:flutter/material.dart';

List<Offset> _drawPoints = <Offset>[];

void main() => runApp(MyDrawApp());

class MyDrawApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            body: DrawCanvas(),
            floatingActionButton: FloatingActionButton(
                child: Icon(Icons.clear),
                onPressed: () {
                  _drawPoints.clear();
                },
            ),
        ),
    );
  }
}

class DrawCanvas extends StatefulWidget {
  @override
  _DrawCanvasState createState() => _DrawCanvasState();
}

class _DrawCanvasState extends State<DrawCanvas> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ClipPath(
        child: detectGestureForPainting(),
        clipper: UpperCaseA(),
      ),
    );
  }

  Widget detectGestureForPainting() {
    return GestureDetector(
      onPanUpdate: (DragUpdateDetails details) {
        setState(() {
          RenderBox object = context.findRenderObject();
          Offset _localPosition = object.globalToLocal(details.globalPosition);
          _drawPoints = List.from(_drawPoints)..add(_localPosition);
        });
      },
      onPanEnd: (DragEndDetails details) => _drawPoints.add(null),
      child: CustomPaint(
        painter: PaintBrush(points: _drawPoints),
        child: Container(
          width: 500,
          height: 900,
        ),
        // size: Size.fromHeight(375),
      ),
    );
  }
}


class UpperCaseA extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    double _width = size.width;
    double _height = size.height;

    Path mypath = Path();

    print("Height = ${size.height}");
    print("Width = ${size.width}");

    mypath.moveTo(_width * 0.496, _height * 0.4373297);
    mypath.lineTo(_width * 0.330666667, _height * 0.671662125);
    mypath.lineTo(_width * 0.208, _height * 0.648501362);
    mypath.lineTo(_width * 0.434666667, _height * 0.328337875);
    mypath.lineTo(_width * 0.562666667, _height * 0.326975477);
    mypath.lineTo(_width * 0.789333333, _height * 0.648501362);
    mypath.lineTo(_width * 0.666666667, _height * 0.671662125);
    mypath.lineTo(_width * 0.610666667, _height * 0.59400545);
    mypath.lineTo(_width * 0.384, _height * 0.59400545);
    mypath.lineTo(_width * 0.432, _height * 0.525885559);
    mypath.lineTo(_width * 0.562666667, _height * 0.525885559);
    mypath.close();

    mypath.addArc(Rect.fromCircle(
            center: Offset(_width * 0.27, _height * 0.66),
            radius: _width * 0.0652), 0, 360);
    mypath.addArc(
        Rect.fromCircle(
            center: Offset(_width * 0.496, _height * 0.34),
            radius: _width * 0.0652), 0, 360);
    mypath.addArc(
        Rect.fromCircle(
            center: Offset(_width * 0.501, _height * 0.34),
            radius: _width * 0.0652),
        0,
        360);
    mypath.addArc(
        Rect.fromCircle(
            center: Offset(_width * 0.728, _height * 0.66),
            radius: _width * 0.0652),
        0,
        360);

    return mypath;

    // return Path.combine(PathOperation.reverseDifference, path, path1);
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}

class PaintBrush extends CustomPainter {
  List<Offset> points;

  PaintBrush({this.points});

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawColor(Colors.grey[350], BlendMode.src);

    Paint paint = new Paint()
      ..color = Colors.blueAccent.shade700
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 100.0;

    for (int i = 0; i < points.length - 1; i++) {
      if (points[i] != null && points[i + 1] != null) {
        print("points[$i] = ${points[i]}");
        canvas.drawLine(points[i], points[i + 1], paint);
      }
    }
  }

  @override
  bool shouldRepaint(PaintBrush oldDelegate) => oldDelegate.points != points;
}

任何人都可以建议:

  1. 由于所选的笔划宽度为100.0,因此涂料溢出到另一部分,如何将其限制为所需的描迹路径。

  2. 最具挑战性的是弯曲的边缘,例如:“ B”,我该如何实现?

  3. 可以使用纹理代替普通涂料。

我知道有太多问题要问,但是任何帮助/建议/文档/示例代码都会帮助很多。感谢您的辛勤工作。

提前谢谢!

0 个答案:

没有答案