Как ограничить изображение на холсте - PullRequest
0 голосов
/ 20 февраля 2020

Я хотел бы нарисовать изображение 200x200 пикселей на холсте, а затем сделать с ним некоторые другие вещи. У меня есть изображение размером 900x690, поэтому в идеале я хотел бы «обрезать» изображение по центру, чтобы использовать термин Android. Это видео по какой-то причине говорит нам использовать FittedBox, а затем SizedBox. Я также попытался поместить оба из них в Container. Я попытался установить размер контейнера, размер ящика и художник Size на 200x200, и все получилось в полноэкранном изображении. Кто знает, что я делаю не так :)

Вот код:

import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  ui.Image image;

  @override
  void initState() {
    super.initState();
    load('images/noodlejpg.jpg').then((i) {
      setState(() {
        image = i;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor: Colors.blue, title: Text('I am a title')),
      backgroundColor: Colors.teal,
      body: SafeArea(
        child: FittedBox(
          child: SizedBox(
            width: 200.0,
            height: 200.0,
            child: CustomPaint(
              painter: MyPainter(image),
            ),
          ),
        ),
      ),
    );
  }

  Future<ui.Image> load(String asset) async {
    ByteData data = await rootBundle.load(asset);
    ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
    ui.FrameInfo fi = await codec.getNextFrame();
    return fi.image;
  }
}

class MyPainter extends CustomPainter {
  ui.Image image;

  MyPainter(this.image);

  @override
  void paint(Canvas canvas, Size size) {
    var paint = new Paint();
    paint.blendMode = BlendMode.srcIn;
    paint.isAntiAlias = true;

    if (image != null) canvas.drawImage(image, Offset.zero, paint);
  }

  @override
  bool shouldRepaint(MyPainter oldDelegate) {
    return image != oldDelegate.image;
  }
}

Ответы [ 2 ]

0 голосов
/ 24 февраля 2020

Хорошо, я понял ответ на этот вопрос. Существует встроенная функция рисования под названием paintImage. Я не знаю, почему видео не упоминает об этом, может быть, оно новое.

Так что в самой функции рисования все, что нужно, это:

  @override
  void paint(Canvas canvas, Size size) {
    paintImage(
        canvas: canvas,
        rect: Rect.fromLTRB(0, 0, 200, 200),
        image: image,
        fit: BoxFit.cover);
  }

BoxFit.cover аналогично «центрированию» изображения, которому я верю. В исходном коде вы можете видеть, что он загружает объекты scale / source / dest rect, но ключ к этому - функция drawImageRect.

0 голосов
/ 20 февраля 2020

Установить код изображения c размер: instantiateImageCode c функция

Future<Codec> instantiateImageCodec (
       Uint8List list,
       {int targetWidth,
       int targetHeight}
)
...