如何在 Flutter Canvas 中绘制多个不同旋转的矩形?

How to Draw multiple Rectangle with different rotation in Flutter Canvas?

我正在尝试在 Canvas 中添加多个矩形并使用用户平移操作旋转它们。但是我到现在为止找到的Rect构造函数都是在没有Rotation的情况下绘制它们。我找到了一种方法 canvas.rotate() 可以旋转整个 canvas.

如何实现?在不使用 canvas.rotate() 的情况下处理用户平移操作的矩形旋转的任何代码都会有所帮助。

解决方法很简单,就像@pskink 在上面的评论中回答的那样。

只有 canvas.rotate()canvas.transform() 可以在 flutter 中旋转任何东西 canvas 并且 canvas.scale() 可以缩放它们。

现在,如果您想将一个对象旋转 120 度,再旋转 40 度,您需要将它们绘制在 canvas.save() ... canvas.restore() 块内。那么您的对象将以不同的角度旋转。例如看下面的代码:

import 'dart:async';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:ui' as ui;

const kCanvasSize = 300.0;

class ImageInsideRectPage extends StatefulWidget {
  const ImageInsideRectPage({Key? key}) : super(key: key);

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

class _ImageInsideRectPageState extends State<ImageInsideRectPage> {
  ui.Image? image;

  @override
  void initState() {
    _load('assets/img.png');
    super.initState();
  }

  void _load(String path) async {
    var bytes = await rootBundle.load(path);
    image = await decodeImageFromList(bytes.buffer.asUint8List());
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          decoration: BoxDecoration(
              border: Border.all(color: Colors.greenAccent, width: 2)),
          height: kCanvasSize,
          width: kCanvasSize,
          child: CustomPaint(
            painter: ImageInsideRectangle(context: context, image: image),
            child: SizedBox.expand(),
          ),
        ),
      ),
    );
  }
}

class ImageInsideRectangle extends CustomPainter {
  ImageInsideRectangle({required this.context, required this.image});
  ui.Image? image;
  final BuildContext context;

  @override
  void paint(Canvas canvas, Size size) async {
    canvas.clipRRect(ui.RRect.fromRectXY(
      Rect.fromPoints(Offset(0, 0), Offset(kCanvasSize - 4, kCanvasSize - 4)),
      0,
      0,
    ));
    Paint greenBrush = Paint()..color = Colors.greenAccent;
    if (image != null) {
      canvas.save();
      rotate(
          canvas: canvas,
          cx: image!.width.toDouble() / 2,
          cy: image!.height.toDouble() / 2,
          angle: -0.3);
      canvas.scale(kCanvasSize / image!.height);
      canvas.drawImage(image!, Offset(0, 0), greenBrush);
      canvas.restore();
    }
    canvas.save();
    rotate(canvas: canvas, cx: 200 + 50, cy: 100 + 50, angle: 0.5);
    canvas.drawRect(Rect.fromLTWH(200, 100, 100, 100), greenBrush);
    canvas.restore();
  }

  void rotate(
      {required Canvas canvas,
      required double cx,
      required double cy,
      required double angle}) {
    canvas.translate(cx, cy);
    canvas.rotate(angle);
    canvas.translate(-cx, -cy);
  }

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

Future<ui.Image> loadUiImage(String imageAssetPath) async {
  final ByteData data = await rootBundle.load(imageAssetPath);
  final Completer<ui.Image> completer = Completer();
  ui.decodeImageFromList(Uint8List.view(data.buffer), (ui.Image img) {
    return completer.complete(img);
  });
  return completer.future;
}

这样您就可以在多个方向上旋转多个对象。此外,还有一个从本地资源加载图像并围绕其自身中心旋转的示例。