最近遇到一个项目需求,这里记录下。将图片进行顺时针旋转90°和逆时针90°,保证图片都铺满矩形框区域
import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double rate = 4 / 6;
String imageUrl =
'https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/b2de9c82d158ccbfb40a4fd81bd8bc3eb035419a.jpg';
double imageWidth = 0;
double imageHeight = 0;
double scale = 1;
double angle = 0;
Future? future;
@override
void initState() {
future = download();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF5F9FA),
appBar: AppBar(
title: const Text('图片旋转'),
),
body: FutureBuilder(
future: future,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.data == null) {
return const SizedBox();
}
Uint8List bytes = snapshot.data;
return Column(
children: [
ElevatedButton(
onPressed: () {
changeAngle(false);
},
child: const Text('逆时针')),
ElevatedButton(
onPressed: () {
changeAngle(true);
},
child: const Text('顺时针')),
AspectRatio(
aspectRatio: rate,
child: Container(
width: double.infinity,
height: double.infinity,
color: Colors.blue,
padding: const EdgeInsets.all(6),
child: LayoutBuilder(
builder: (c, b) {
if (angle % pi != 0) {
scale = getMinMaxScaleSingle(b.maxWidth, b.maxHeight);
} else {
scale = 1;
}
return Transform.scale(
scale: scale,
child: Transform.rotate(
angle: angle,
child: Image.memory(bytes),
),
);
},
),
),
)
],
);
},
),
);
}
changeAngle(bool clockwise) {
if (clockwise) {
angle += pi / 2;
if (angle == pi * 2) angle = 0;
} else {
angle -= pi / 2;
if (angle == -pi * 2) angle = 0;
}
if (mounted) setState(() {});
}
//获得单个图片区域的最小最大缩放比例
double getMinMaxScaleSingle(double width, double height) {
final fittedSizes = getFittedSizes(width, height);
double imgWidth = fittedSizes.destination.width;
double imgHeight = fittedSizes.destination.height;
if (angle % pi != 0) {
imgWidth = fittedSizes.destination.height;
imgHeight = fittedSizes.destination.width;
}
double scaleX = width / imgWidth;
double scaleY = height / imgHeight;
double minScale = scaleX > scaleY ? scaleY : scaleX;
return minScale;
}
FittedSizes getFittedSizes(double width, double height) {
return applyBoxFit(
BoxFit.contain, Size(imageWidth, imageHeight), Size(width, height));
}
Future download() async {
var httpClient = HttpClient();
try {
var request = await httpClient.getUrl(Uri.parse(imageUrl));
var response = await request.close();
var imageByte = await consolidateHttpClientResponseBytes(response);
var codec = await ui.instantiateImageCodec(imageByte);
ui.FrameInfo fi = await codec.getNextFrame();
imageWidth = fi.image.width * 1.0;
imageHeight = fi.image.height * 1.0;
return imageByte;
} catch (error) {
return null;
}
}
}