Как ограничить изображение на холсте
Я хотел бы нарисовать на холсте изображение размером 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;
}
}
3 ответа
Хорошо, я нашел ответ на это. Есть встроенная функция рисования под названием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
функция.
Попробуйте так
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: Colors.blue, title: Text('I am a title')),
backgroundColor: Colors.teal,
body: SafeArea(
child: Container(
height: 200.0,
width: 200.0,
child: FittedBox(
child: SizedBox(
height: image.height.toDouble(),
width: image.width.toDouble(),
child: CustomPaint(
painter: MyPainter(image),
),
),
),
),
),
);
}
Установить размер кодека изображения: http://instantiateImageCodec%20function
Future<Codec> instantiateImageCodec (
Uint8List list,
{int targetWidth,
int targetHeight}
)