Flutter自定义绘图插件mini_canvas的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter自定义绘图插件mini_canvas的使用

利用Canvas绘制控件。

mini_canvas

GitHub code size in bytes

导包

import 'package:mini_canvas/mini_canvas.dart';

主要实现的内容

  • 五角星

    五角星

  • 仪表盘

    仪表盘

  • 圆弧

    圆弧

  • 时钟

    时钟

  • 水波纹进度

    水波纹进度

  • 自定义状态图

    自定义状态图

使用

引入库
flutter pub add mini_canvas

更多功能可以clone项目并运行demo。

完整示例Demo

import 'package:flutter/material.dart';

import 'time_clock_page.dart';

import 'package:mini_canvas/mini_canvas.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) => const MaterialApp(home: MyHomePage());
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Widget> items = [];

  [@override](/user/override)
  Widget build(BuildContext context) {
    items.clear();
    initWaveProgress();
    initBashBoarWidget();
    initClockWidget();
    initArcWidgets();
    initFiveWidgets();
    initStateWidgets();
    initStringWidget();
    return Scaffold(
        appBar: AppBar(title: const Text("MiniCanvas 测试页面")),
        backgroundColor: Colors.grey[300],
        body: SingleChildScrollView(
          child: Column(children: items),
        ));
  }

  void initWaveProgress() {
    items.add(_buildItem(
        "波浪进度",
        ListView(
          children: [
            const WaveProgress(
              100,
              20,
              label: '空置面积剩余',
              subLabel: '5000㎡',
            ),
            const WaveProgress(
              300,
              20,
              label: '进度',
            ),
            WaveProgress(
              MediaQuery.of(context).size.width,
              70,
              label: '出勤率',
            ),
          ],
        )));
  }

  void initBashBoarWidget() {
    items.add(_buildItem(
        "仪表盘",
        ListView(
          children: [
            const BashBoardWidget(100,
                strokeWidth: 8, label: '收缴率', value: 68.23),
            const BashBoardWidget(300,
                strokeWidth: 10, label: '出勤率', value: 100),
            BashBoardWidget(MediaQuery.of(context).size.width,
                strokeWidth: 20, label: '出租率', value: 35.33),
          ],
        )));
  }

  void initClockWidget() {
    items.add(_buildItem("时钟", const TimeClockPage()));
  }

  void initStringWidget() {
    items.add(_buildItem(
        "旋转字符串",
        const Stack(
          children: [
            StringWidget(
              "↖",
              width: 100,
              height: 100,
              horizontalTextAlign: TextAlign.left,
              verticalAlign: VerticalAlign.top,
            ),
            StringWidget(
              "↑",
              width: 100,
              height: 100,
              horizontalTextAlign: TextAlign.center,
              verticalAlign: VerticalAlign.top,
            ),
            StringWidget(
              "↗",
              width: 100,
              height: 100,
              horizontalTextAlign: TextAlign.right,
              verticalAlign: VerticalAlign.top,
            ),
            StringWidget(
              "←",
              width: 100,
              height: 100,
              horizontalTextAlign: TextAlign.left,
              verticalAlign: VerticalAlign.center,
            ),
            StringWidget(
              "+",
              width: 100,
              height: 100,
              horizontalTextAlign: TextAlign.center,
              verticalAlign: VerticalAlign.center,
            ),
            StringWidget(
              "→",
              width: 100,
              height: 100,
              horizontalTextAlign: TextAlign.right,
              verticalAlign: VerticalAlign.center,
            ),
            StringWidget(
              "↙",
              width: 100,
              height: 100,
              horizontalTextAlign: TextAlign.left,
              verticalAlign: VerticalAlign.bottom,
            ),
            StringWidget(
              "↓",
              width: 100,
              height: 100,
              horizontalTextAlign: TextAlign.center,
              verticalAlign: VerticalAlign.bottom,
            ),
            StringWidget(
              "↘",
              width: 100,
              height: 100,
              horizontalTextAlign: TextAlign.right,
              verticalAlign: VerticalAlign.bottom,
            )
          ],
        )));
  }

  void initStateWidgets() {
    items.add(_buildItem(
        "状态图标",
        const Wrap(
          children: [
            StateWidget("进行中", color: Colors.blue, size: 60),
            StateWidget("已删除", color: Colors.red, size: 100, fontSize: 18),
            StateWidget("已完成", color: Colors.green, size: 180, fontSize: 38)
          ],
        )));
  }

  void initFiveWidgets() {
    items.add(_buildItem(
        "五角星",
        const Wrap(
          children: [
            FiveStarWidget(50),
            FiveStarWidget(50, rotateAngle: 30),
            FiveStarWidget(50, rotateAngle: 60, color: Colors.blue),
            FiveStarWidget(50, rotateAngle: 90, color: Colors.blue),
            FiveStarWidget(50, rotateAngle: 120),
            FiveStarWidget(50, rotateAngle: 140)
          ],
        )));
  }

  void initArcWidgets() {
    items.add(_buildItem(
        "圆弧、圆",
        Wrap(
          children: [
            ArcWidget(50,
                startAngle: 0.0,
                sweepAngle: 300.0,
                color: Colors.red,
                strokeWidth: 15,
                borderColor: Colors.grey[200]!),
            ArcWidget(100,
                startAngle: 0.0,
                sweepAngle: 90.0,
                color: Colors.red,
                strokeWidth: 15,
                borderColor: Colors.grey[200]!),
            ArcWidget(200,
                startAngle: 270.0,
                sweepAngle: 90.0,
                color: Colors.red,
                strokeWidth: 15,
                borderColor: Colors.grey[200]!),
            const ArcWidget(300,
                startAngle: 0.0,
                sweepAngle: 360.0,
                color: Colors.red,
                strokeWidth: 10),
            const ArcWidget(50, color: Colors.red),
            const ArcWidget(50, startAngle: 0.0, sweepAngle: 90.0),
            const ArcWidget(50, startAngle: 0.0, sweepAngle: 180.0),
            const ArcWidget(50, startAngle: 0.0, sweepAngle: 270.0),
          ],
        )));
  }

  Widget _buildItem(String title, Widget widget) =>
      ListTile(title: Text(title), onTap: () => gotoPage(widget, title));

  void gotoPage(Widget widget, String title) => Navigator.push(
      context,
      MaterialPageRoute(
          builder: (ctx) =>
              Scaffold(appBar: AppBar(title: Text(title)), body: widget)));
}

更多关于Flutter自定义绘图插件mini_canvas的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自定义绘图插件mini_canvas的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter中使用自定义绘图插件mini_canvas的示例代码。请注意,mini_canvas并非一个官方的Flutter插件,因此这个示例假设你已经有一个名为mini_canvas的插件,并且该插件提供了基本的绘图功能。如果mini_canvas插件的API有所不同,请根据实际的文档进行调整。

首先,确保你已经在pubspec.yaml文件中添加了mini_canvas依赖:

dependencies:
  flutter:
    sdk: flutter
  mini_canvas: ^x.y.z  # 替换为实际的版本号

然后,运行flutter pub get来获取依赖。

接下来,我们编写一个Flutter应用,展示如何使用mini_canvas进行自定义绘图。假设mini_canvas提供了一个MiniCanvas小部件,允许我们进行绘图操作。

import 'package:flutter/material.dart';
import 'package:mini_canvas/mini_canvas.dart'; // 假设插件的主文件是mini_canvas.dart

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Mini Canvas Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Mini Canvas Demo'),
        ),
        body: Center(
          child: CustomDrawing(),
        ),
      ),
    );
  }
}

class CustomDrawing extends StatefulWidget {
  @override
  _CustomDrawingState createState() => _CustomDrawingState();
}

class _CustomDrawingState extends State<CustomDrawing> {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 300,
      width: 300,
      child: MiniCanvas(
        onDraw: (Canvas canvas, Size size) {
          // 绘制背景颜色
          final paint = Paint()
            ..color = Colors.white
            ..style = PaintingStyle.fill;
          canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);

          // 绘制一个红色矩形
          final rectPaint = Paint()
            ..color = Colors.red
            ..style = PaintingStyle.fill;
          canvas.drawRect(Rect.fromLTWH(50, 50, 100, 100), rectPaint);

          // 绘制一条蓝色直线
          final linePaint = Paint()
            ..color = Colors.blue
            ..strokeWidth = 4.0;
          canvas.drawLine(Offset(50, 200), Offset(200, 50), linePaint);

          // 绘制一些文本
          final textPaint = TextPaint()
            ..color = Colors.black
            ..style = TextStyle(fontSize: 24);
          canvas.drawText('Hello Mini Canvas!', Offset(100, 250), textPaint);
        },
      ),
    );
  }
}

// 假设TextPaint是一个自定义的Paint类,用于绘制文本(如果mini_canvas没有提供,需要自定义)
class TextPaint extends Paint {
  TextStyle style;

  @override
  void draw(Canvas canvas, String text, Offset position) {
    final TextPainter textPainter = TextPainter(
      text: TextSpan(text: text, style: style),
      textAlign: TextAlign.left,
      textDirection: TextDirection.ltr,
    );
    textPainter.layout(minWidth: 0, maxWidth: double.infinity);
    textPainter.paint(canvas, position);
  }
}

// 注意:如果mini_canvas插件提供了自己的绘图API,请直接使用它们,而不是上面的TextPaint类。
// 上面的TextPaint类只是为了演示如何可能扩展Paint类以支持文本绘制。

在这个示例中,我们创建了一个CustomDrawing小部件,它使用MiniCanvas来绘制一些基本的图形,包括一个矩形、一条直线和一些文本。请注意,TextPaint类是一个假设的类,用于演示如何可能扩展Paint类以支持文本绘制。实际使用时,你应该根据mini_canvas插件提供的API进行相应的调整。

如果mini_canvas插件提供了不同的绘图API或者需要不同的配置,请参考该插件的官方文档进行调整。

回到顶部