简体   繁体   English

在 Flutter 中将具有自定义大小和旋转的图像绘制到 CustomPaint 中

[英]Draw an image with custom Size and Rotation into a CustomPaint in Flutter

How can I draw an image to a customPaint() specifying its size and rotation in Flutter?如何在 Flutter 中将图像绘制到指定其大小和旋转的customPaint() Normally with only drawImage() the image gets drawn with its dimensions being its dimensions in pixels.通常只使用drawImage()绘制图像,其尺寸是以像素为单位的尺寸。 For example, a 40x40 pixels image gets drawn with dimensions of 40 by 40. How can I draw the same image but for example with a size of 80x80 and a rotation of 120°?例如,一张 40x40 像素的图像以 40 x 40 的尺寸绘制。如何绘制相同的图像,但例如尺寸为 80x80 且旋转 120°? I've tried drawAtlas but I couldn't find anything online.我试过drawAtlas但我在网上找不到任何东西。

This is the code I have to draw.这是我必须绘制的代码。 (It draws a 20x20 rectangle at the top-right of the screen). (它在屏幕右上角绘制了一个 20x20 的矩形)。

class ParticlePainter extends CustomPainter {
  final List<GameObject> objects;

  @override
  void paint(Canvas canvas, Size size) {


    canvas.drawRect(

        Rect.fromCenter(
            height: 20,
            width: 20,
            center: Offset(0.0, 0.0)),

        Paint()
          ..color = Colors.red
          ..blendMode = BlendMode.darken);
    }

  }

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

  ParticlePainter(this.objects);
}

To get the image I'm using the code in this video: Custom Paint in Flutter要获取图像,我正在使用此视频中的代码: Flutter 中的自定义绘画

Future<Image> _loadImage(File file) async{
   final data = await file.readAsBytesSync();
   return await decodeImageFromList(data);
}

It looks like you can rotate the canvas itself in your paint function.看起来您可以在油漆 function 中旋转 canvas 本身。 My code is below.我的代码如下。

import 'package:flutter/material.dart';
import 'dart:math' as math;

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

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

class ParticlePainter extends CustomPainter {
  // final List<GameObject> objects;

  @override
  void paint(Canvas canvas, Size size) {
    canvas.save();

    final degrees = 120;
    final radians = degrees * math.pi / 180;

    canvas.rotate(radians);

    canvas.drawRect(
        Rect.fromCenter(
          height: 20,
          width: 20,
          center: Offset(
            0.0,
            0.0,
          ),
        ),
        Paint()
          ..color = Colors.red
          ..blendMode = BlendMode.darken);

    canvas.restore();
  }

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

  // ParticlePainter(this.objects);
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Yay"),
      ),
      body: CustomPaint(
        child: Container(),
        painter: ParticlePainter(),
      ),
    );
  }
}

For me, this causes the box to go off screen a bit, but I hope it is enough for you to move forward.对我来说,这会导致 go 的框有点离屏,但我希望这足以让你继续前进。 If you're doing something easy, you might be able to use either Transform.rotate or RotatedBox and wrap your CustomPaint in it.如果您正在做一些简单的事情,您也许可以使用Transform.rotateRotatedBox并将您的CustomPaint包装在其中。

It's a long time since the question was asked but I want to fulfill the answer for future readers, as the above answer does not answer it for multiple objects.自问这个问题以来已经有很长时间了,但我想为未来的读者完成答案,因为上面的答案并没有为多个对象回答。

There is only canvas.rotate() and canvas.transform() to rotate anything in the flutter canvas and there is canvas.scale() to scale them.只有canvas.rotate()canvas.transform()可以旋转 flutter canvas 中的任何内容,并且有canvas.scale()可以缩放它们。

now if you want to rotate one object 120, and another 40 degrees you need to draw them inside a canvas.save() ... canvas.restore() block.现在,如果你想旋转一个 object 120,另一个 40 度,你需要将它们绘制在canvas.save() ... canvas.restore()块中。 then your objects will be rotated at a different angles.那么您的对象将以不同的角度旋转。 look at the below code看看下面的代码

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;
}

This way you can rotate multiple objects in multiple directions.这样您就可以在多个方向上旋转多个对象。 also, there is an example of loading an image from local asset and rotating the image around its own center.此外,还有一个从本地资产加载图像并围绕其自身中心旋转图像的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM