如何在 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;
}
这样您就可以在多个方向上旋转多个对象。此外,还有一个从本地资源加载图像并围绕其自身中心旋转的示例。
我正在尝试在 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;
}
这样您就可以在多个方向上旋转多个对象。此外,还有一个从本地资源加载图像并围绕其自身中心旋转的示例。