如何在颤振中绘制这个自定义形状?

时间:2021-02-11 06:02:33

标签: flutter

如何绘制这个自定义形状? 注意这个形状不同于半圆 我在颤振中实现下图时遇到问题

tnx

[1]:[这张图片] [1]:https://i.stack.imgur.com/KsBcx.png

3 个答案:

答案 0 :(得分:1)

1.为图片创建一个svg文件

  • 使用 Figma,为共享的图像创建一个矢量。

  • 以 svg 格式导出矢量。

2.获取路径

  • 您可以通过两种方式打开 svg 文件以获取其内容:

    i) 通过浏览器打开并转到检查元素

    ii) 使用记事本或记事本++打开文件

  • 以下是步骤 1

    中创建的 svg 的内容
<svg width="474" height="157" viewBox="0 0 474 157" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M45 141L1 156H473L444 149L420 141L398 126L378 106L357 80L334 53L318 35L299 17L270 6L236 1H198L170 11L147 30L124 53L102 80L84 100L65 126L45 141Z" stroke="black"/>
</svg>
  • 从路径属性获取路径字符串:
M45 141L1 156H473L444 149L420 141L398 126L378 106L357 80L334 53L318 35L299 17L270 6L236 1H198L170 11L147 30L124 53L102 80L84 100L65 126L45 141Z

3.在 Flutter 上实现

  • 使用名为 CustomPath
  • 的有状态小部件创建一个新的 dart 文件
import 'package:flutter/material.dart';

class CustomPath extends StatefulWidget {
  @override
  _CustomPathState createState() => _CustomPathState();
}

class _CustomPathState extends State<CustomPath> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      
    );
  }
}

在本课程中,您将只做两件事:

  • 添加 ClipPath 小部件
  • 在同一文件中创建一个类,用于扩展定义图像路径的 CustomClipper,并将添加到 clipper 小部件的 ClipPath 属性中。

4.创建扩展CustomClipper的类

  • 就我而言,我将类命名为 BezierClipper,其方法为 shouldReclip()
class BezierClipper extends CustomClipper<Path> {

  @override
  bool shouldReclip(oldClipper) => false;
}
  • 然后通过添加我们在步骤 2 中获得的 Path 来添加使用此 link 生成的 getClip() 方法
class BezierClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    Path path = Path();
    final double _xScaling = size.width / 414;
    final double _yScaling = size.height / 896;
    path.lineTo(45 * _xScaling, 141 * _yScaling);
    path.cubicTo(
      45 * _xScaling,
      141 * _yScaling,
      1 * _xScaling,
      156 * _yScaling,
      1 * _xScaling,
      156 * _yScaling,
    );
    path.cubicTo(
      1 * _xScaling,
      156 * _yScaling,
      473 * _xScaling,
      156 * _yScaling,
      473 * _xScaling,
      156 * _yScaling,
    );
    path.cubicTo(
      473 * _xScaling,
      156 * _yScaling,
      444 * _xScaling,
      149 * _yScaling,
      444 * _xScaling,
      149 * _yScaling,
    );
    path.cubicTo(
      444 * _xScaling,
      149 * _yScaling,
      420 * _xScaling,
      141 * _yScaling,
      420 * _xScaling,
      141 * _yScaling,
    );
    path.cubicTo(
      420 * _xScaling,
      141 * _yScaling,
      398 * _xScaling,
      126 * _yScaling,
      398 * _xScaling,
      126 * _yScaling,
    );
    path.cubicTo(
      398 * _xScaling,
      126 * _yScaling,
      378 * _xScaling,
      106 * _yScaling,
      378 * _xScaling,
      106 * _yScaling,
    );
    path.cubicTo(
      378 * _xScaling,
      106 * _yScaling,
      357 * _xScaling,
      80 * _yScaling,
      357 * _xScaling,
      80 * _yScaling,
    );
    path.cubicTo(
      357 * _xScaling,
      80 * _yScaling,
      334 * _xScaling,
      53 * _yScaling,
      334 * _xScaling,
      53 * _yScaling,
    );
    path.cubicTo(
      334 * _xScaling,
      53 * _yScaling,
      318 * _xScaling,
      35 * _yScaling,
      318 * _xScaling,
      35 * _yScaling,
    );
    path.cubicTo(
      318 * _xScaling,
      35 * _yScaling,
      299 * _xScaling,
      17 * _yScaling,
      299 * _xScaling,
      17 * _yScaling,
    );
    path.cubicTo(
      299 * _xScaling,
      17 * _yScaling,
      270 * _xScaling,
      6 * _yScaling,
      270 * _xScaling,
      6 * _yScaling,
    );
    path.cubicTo(
      270 * _xScaling,
      6 * _yScaling,
      236 * _xScaling,
      1 * _yScaling,
      236 * _xScaling,
      1 * _yScaling,
    );
    path.cubicTo(
      236 * _xScaling,
      1 * _yScaling,
      198 * _xScaling,
      1 * _yScaling,
      198 * _xScaling,
      1 * _yScaling,
    );
    path.cubicTo(
      198 * _xScaling,
      1 * _yScaling,
      170 * _xScaling,
      11 * _yScaling,
      170 * _xScaling,
      11 * _yScaling,
    );
    path.cubicTo(
      170 * _xScaling,
      11 * _yScaling,
      147 * _xScaling,
      30 * _yScaling,
      147 * _xScaling,
      30 * _yScaling,
    );
    path.cubicTo(
      147 * _xScaling,
      30 * _yScaling,
      124 * _xScaling,
      53 * _yScaling,
      124 * _xScaling,
      53 * _yScaling,
    );
    path.cubicTo(
      124 * _xScaling,
      53 * _yScaling,
      102 * _xScaling,
      80 * _yScaling,
      102 * _xScaling,
      80 * _yScaling,
    );
    path.cubicTo(
      102 * _xScaling,
      80 * _yScaling,
      84 * _xScaling,
      100 * _yScaling,
      84 * _xScaling,
      100 * _yScaling,
    );
    path.cubicTo(
      84 * _xScaling,
      100 * _yScaling,
      65 * _xScaling,
      126 * _yScaling,
      65 * _xScaling,
      126 * _yScaling,
    );
    path.cubicTo(
      65 * _xScaling,
      126 * _yScaling,
      45 * _xScaling,
      141 * _yScaling,
      45 * _xScaling,
      141 * _yScaling,
    );
    path.cubicTo(
      45 * _xScaling,
      141 * _yScaling,
      45 * _xScaling,
      141 * _yScaling,
      45 * _xScaling,
      141 * _yScaling,
    );
    return path;
  }

  @override
  bool shouldReclip(oldClipper) => true;
}

5.更新CustomPath类

  • 添加将裁剪 CustomClipper 的 ClipPath,在本例中称为 BezierClipper

  • 然后添加一个 Container 作为它的子元素,它将符合新的形状。

  • 像这样:

class _CustomPathState extends State<CustomPath> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(),
        body: ClipPath(
          clipper: BezierClipper(),
          child:
              Container(alignment: Alignment.center, color: Colors.black),
        ));
  }
}

6.完整代码

import 'package:flutter/material.dart';

class CustomPath extends StatefulWidget {
  @override
  _CustomPathState createState() => _CustomPathState();
}

class _CustomPathState extends State<CustomPath> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(),
        body: ClipPath(
          clipper: BezierClipper(),
          child:
              Container(alignment: Alignment.center, color: Colors.black),
        ));
  }
}

class BezierClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    Path path = Path();
    final double _xScaling = size.width / 414;
    final double _yScaling = size.height / 896;
    path.lineTo(45 * _xScaling, 141 * _yScaling);
    path.cubicTo(
      45 * _xScaling,
      141 * _yScaling,
      1 * _xScaling,
      156 * _yScaling,
      1 * _xScaling,
      156 * _yScaling,
    );
    path.cubicTo(
      1 * _xScaling,
      156 * _yScaling,
      473 * _xScaling,
      156 * _yScaling,
      473 * _xScaling,
      156 * _yScaling,
    );
    path.cubicTo(
      473 * _xScaling,
      156 * _yScaling,
      444 * _xScaling,
      149 * _yScaling,
      444 * _xScaling,
      149 * _yScaling,
    );
    path.cubicTo(
      444 * _xScaling,
      149 * _yScaling,
      420 * _xScaling,
      141 * _yScaling,
      420 * _xScaling,
      141 * _yScaling,
    );
    path.cubicTo(
      420 * _xScaling,
      141 * _yScaling,
      398 * _xScaling,
      126 * _yScaling,
      398 * _xScaling,
      126 * _yScaling,
    );
    path.cubicTo(
      398 * _xScaling,
      126 * _yScaling,
      378 * _xScaling,
      106 * _yScaling,
      378 * _xScaling,
      106 * _yScaling,
    );
    path.cubicTo(
      378 * _xScaling,
      106 * _yScaling,
      357 * _xScaling,
      80 * _yScaling,
      357 * _xScaling,
      80 * _yScaling,
    );
    path.cubicTo(
      357 * _xScaling,
      80 * _yScaling,
      334 * _xScaling,
      53 * _yScaling,
      334 * _xScaling,
      53 * _yScaling,
    );
    path.cubicTo(
      334 * _xScaling,
      53 * _yScaling,
      318 * _xScaling,
      35 * _yScaling,
      318 * _xScaling,
      35 * _yScaling,
    );
    path.cubicTo(
      318 * _xScaling,
      35 * _yScaling,
      299 * _xScaling,
      17 * _yScaling,
      299 * _xScaling,
      17 * _yScaling,
    );
    path.cubicTo(
      299 * _xScaling,
      17 * _yScaling,
      270 * _xScaling,
      6 * _yScaling,
      270 * _xScaling,
      6 * _yScaling,
    );
    path.cubicTo(
      270 * _xScaling,
      6 * _yScaling,
      236 * _xScaling,
      1 * _yScaling,
      236 * _xScaling,
      1 * _yScaling,
    );
    path.cubicTo(
      236 * _xScaling,
      1 * _yScaling,
      198 * _xScaling,
      1 * _yScaling,
      198 * _xScaling,
      1 * _yScaling,
    );
    path.cubicTo(
      198 * _xScaling,
      1 * _yScaling,
      170 * _xScaling,
      11 * _yScaling,
      170 * _xScaling,
      11 * _yScaling,
    );
    path.cubicTo(
      170 * _xScaling,
      11 * _yScaling,
      147 * _xScaling,
      30 * _yScaling,
      147 * _xScaling,
      30 * _yScaling,
    );
    path.cubicTo(
      147 * _xScaling,
      30 * _yScaling,
      124 * _xScaling,
      53 * _yScaling,
      124 * _xScaling,
      53 * _yScaling,
    );
    path.cubicTo(
      124 * _xScaling,
      53 * _yScaling,
      102 * _xScaling,
      80 * _yScaling,
      102 * _xScaling,
      80 * _yScaling,
    );
    path.cubicTo(
      102 * _xScaling,
      80 * _yScaling,
      84 * _xScaling,
      100 * _yScaling,
      84 * _xScaling,
      100 * _yScaling,
    );
    path.cubicTo(
      84 * _xScaling,
      100 * _yScaling,
      65 * _xScaling,
      126 * _yScaling,
      65 * _xScaling,
      126 * _yScaling,
    );
    path.cubicTo(
      65 * _xScaling,
      126 * _yScaling,
      45 * _xScaling,
      141 * _yScaling,
      45 * _xScaling,
      141 * _yScaling,
    );
    path.cubicTo(
      45 * _xScaling,
      141 * _yScaling,
      45 * _xScaling,
      141 * _yScaling,
      45 * _xScaling,
      141 * _yScaling,
    );
    return path;
  }

  @override
  bool shouldReclip(oldClipper) => true;
}

答案 1 :(得分:0)

创建一个 StatelessWidget,比如接受直径的 MyArc。

class MyArc extends StatelessWidget {
  final double diameter;

  const MyArc({Key key, this.diameter = 200}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: MyPainter(),
      size: Size(diameter, diameter),
    );
  }
}

// This is the Painter class
class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..color = Colors.blue;
    canvas.drawArc(
      Rect.fromCenter(
        center: Offset(size.height / 2, size.width / 2),
        height: size.height,
        width: size.width,
      ),
      math.pi,
      math.pi,
      false,
      paint,
    );
  }

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

用法:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(),
    body: MyArc(diameter: 300),
  );
}

答案 2 :(得分:0)

这种形状需要贝塞尔曲线来制作。

如果您可以将此图像创建为 SVG,则可以使用 this tool 创建可在 Flutter 中使用的 ClipPath。

有关如何使用 ClipPath 的一些阅读:https://medium.com/flutterdevs/custom-clipping-in-flutter-8aa0631ef19b