Flutter画布堆叠插件stack_canvas的使用

Flutter画布堆叠插件stack_canvas的使用

stack_canvas 是一个简单的画布组件,可以自由地以类似画布的方式放置小部件。通过将小部件包装在一个 CanvasObject 中,并指定其偏移量和大小,可以在画布上自由布局。

此外,该画布还提供了变换工具,用于缩放和移动画布。所有画布变换都可以进行动画处理。

请参阅示例应用程序以获取全面的演示。

安装

pubspec.yaml 文件中添加 stack_canvas 作为依赖项。

dependencies:
  stack_canvas: ^x.x.x

导入 stack_canvas

import 'package:stack_canvas/stack_canvas.dart';

如何使用

首先,使用 StackCanvas 小部件将一个新的画布嵌入到您的视图中。这是一个空画布。

class MyView extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      child: StackCanvas(
        controller: StackCanvasController(),
      ),
    );
  }
}

空画布

Empty Canvas

如果您需要添加对象(显然),则使用 StackCanvasController。通过此控制器,添加、删除和变换画布变得非常简单。

final StackCanvasController controller = StackCanvasController();

将其传递给要控制的 StackCanvas

StackCanvas(
  controller: controller,
),

现在,我们可以添加任何我们喜欢的小部件,只需将其包裹在 CanvasObject 中即可。CanvasObject 实际上是一个泛型类型,定义为 CanvasObject<T>;但是,大多数情况下,它将是 CanvasObject<Widget>,因为我们正在使用 Flutter。

List<CanvasObject<Widget>> objects = [
  CanvasObject<Widget>(
    dx: 100,             // X轴偏移
    dy: 100,             // Y轴偏移
    width: 80,
    height: 40,
    child: Container(    // 渲染的小部件
      color: Colors.red,
    )
  )
];

当然,您可以一次添加多个对象。

然后使用控制器将这些小部件对象添加到画布中。

controller.addCanvasObjects(objects);

这样就完成了!

带有小部件的画布

单个小部件

缩放与移动

缩放

controller.zoomIn();   // 放大
controller.zoomOut();  // 缩小

移动

controller.moveUp();   // 向上移动
controller.moveDown(); // 向下移动
controller.moveLeft(); // 向左移动
controller.moveRight();// 向右移动

自定义画布

以下是所有可自定义的属性及其默认值。

StackCanvas(
  width: double.maxFinite,      // 全宽
  height: double.maxFinite,     // 全高
  backgroundColor: Colors.white,
  animationDuration: Duration(milliseconds: 400),
  controller: controller,
  disposeController: true,      // 如果设置为 false,则需要手动处置控制器
)
StackCanvasController(
  zoomChangeUnit: 0.10,         // 缩放速度(缩放因子)
  moveChangeUnit: 30.00,        // 移动速度(平移值)
  offsetReference: Reference.TopLeft,
  zoomReference: Reference.TopLeft,
)

示例

示例 1

画布变换

变换

示例 2

生长三角形

生长三角形

示例代码

import 'package:flutter/material.dart';
import 'package:stack_canvas/stack_canvas.dart';

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

class App extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  [@override](/user/override)
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final StackCanvasController controller = StackCanvasController(
    offsetReference: Reference.Center,
    zoomReference: Reference.Center,
  );

  [@override](/user/override)
  void initState() {
    super.initState();

    // 添加虚拟对象
    controller.addCanvasObjects([
      CanvasObject<Widget>(
        dx: -100,
        dy: -100,
        width: 40,
        height: 60,
        child: Container(
          color: Colors.red,
        ),
      ),
      CanvasObject<Widget>(
        dx: 30,
        dy: -120,
        width: 80,
        height: 80,
        child: Container(
          color: Colors.blue,
        ),
      ),
      CanvasObject<Widget>(
        dx: 10,
        dy: -20,
        width: 100,
        height: 60,
        child: Container(
          color: Colors.purple,
        ),
      ),
    ]);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Stack Canvas"),
        actions: [
          IconButton(
            icon: Icon(Icons.arrow_drop_up_rounded),
            tooltip: "向上移动",
            onPressed: () {
              controller.moveUp();
            },
          ),
          IconButton(
            icon: Icon(Icons.arrow_drop_down_rounded),
            tooltip: "向下移动",
            onPressed: () {
              controller.moveDown();
            },
          ),
          IconButton(
            icon: Icon(Icons.arrow_left_rounded),
            tooltip: "向左移动",
            onPressed: () {
              controller.moveLeft();
            },
          ),
          IconButton(
            icon: Icon(Icons.arrow_right_rounded),
            tooltip: "向右移动",
            onPressed: () {
              controller.moveRight();
            },
          ),
          IconButton(
            icon: Icon(Icons.zoom_in_rounded),
            tooltip: "放大",
            onPressed: () {
              controller.zoomIn();
            },
          ),
          IconButton(
            icon: Icon(Icons.zoom_out_rounded),
            tooltip: "缩小",
            onPressed: () {
              controller.zoomOut();
            },
          ),
        ],
      ),
      body: Center(
        child: StackCanvas(
          width: double.maxFinite,
          height: double.maxFinite,
          canvasController: controller,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        tooltip: '重置画布变换',
        child: Icon(Icons.refresh_rounded),
        onPressed: () {
          controller.resetCanvasTransformation();
        },
      ),
    );
  }
}

更多关于Flutter画布堆叠插件stack_canvas的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter画布堆叠插件stack_canvas的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


stack_canvas 是一个用于在 Flutter 中实现画布堆叠的插件。它允许你在一个画布上叠加多个图层,并且可以独立地绘制和操作每个图层。这个插件非常适合需要复杂绘图和图层管理的应用场景。

安装

首先,你需要在 pubspec.yaml 文件中添加 stack_canvas 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  stack_canvas: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装依赖。

基本用法

  1. 导入包

    在你的 Dart 文件中导入 stack_canvas 包:

    import 'package:stack_canvas/stack_canvas.dart';
    
  2. 创建 StackCanvas

    StackCanvas 是一个继承自 CustomPaint 的小部件,它允许你在画布上叠加多个图层。

    StackCanvas(
      layers: [
        Layer(
          painter: BackgroundPainter(),
        ),
        Layer(
          painter: ForegroundPainter(),
        ),
      ],
    );
    
  3. 创建 CustomPainter

    每个图层需要一个 CustomPainter 来定义绘制逻辑。你可以创建多个 CustomPainter 类来实现不同的绘制效果。

    class BackgroundPainter extends CustomPainter {
      [@override](/user/override)
      void paint(Canvas canvas, Size size) {
        final paint = Paint()..color = Colors.blue;
        canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);
      }
    
      [@override](/user/override)
      bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
    }
    
    class ForegroundPainter extends CustomPainter {
      [@override](/user/override)
      void paint(Canvas canvas, Size size) {
        final paint = Paint()..color = Colors.red;
        canvas.drawCircle(Offset(size.width / 2, size.height / 2), 50, paint);
      }
    
      [@override](/user/override)
      bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
    }
    
  4. 使用 StackCanvas

    在你的小部件树中使用 StackCanvas,并传入你定义的图层。

    class MyHomePage extends StatelessWidget {
      [@override](/user/override)
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('StackCanvas Example'),
          ),
          body: Center(
            child: StackCanvas(
              layers: [
                Layer(
                  painter: BackgroundPainter(),
                ),
                Layer(
                  painter: ForegroundPainter(),
                ),
              ],
            ),
          ),
        );
      }
    }
    

高级用法

  • 图层交互:你可以通过 Layerinteraction 属性来定义图层的交互行为,例如点击、拖动等。

  • 动态更新:你可以通过 setState 来动态更新图层的绘制逻辑,实现动态效果。

  • 性能优化:对于复杂的绘图场景,可以通过 shouldRepaint 方法来优化绘制性能,避免不必要的重绘。

示例代码

以下是一个完整的示例代码,展示了如何使用 stack_canvas 插件:

import 'package:flutter/material.dart';
import 'package:stack_canvas/stack_canvas.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'StackCanvas Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('StackCanvas Example'),
      ),
      body: Center(
        child: StackCanvas(
          layers: [
            Layer(
              painter: BackgroundPainter(),
            ),
            Layer(
              painter: ForegroundPainter(),
            ),
          ],
        ),
      ),
    );
  }
}

class BackgroundPainter extends CustomPainter {
  [@override](/user/override)
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.blue;
    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);
  }

  [@override](/user/override)
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

class ForegroundPainter extends CustomPainter {
  [@override](/user/override)
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.red;
    canvas.drawCircle(Offset(size.width / 2, size.height / 2), 50, paint);
  }

  [@override](/user/override)
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
回到顶部