Flutter作为iOS框架时Canvas drawImage返回空白问题求助
问题解决:Flutter模块集成iOS后Canvas旋转图片返回空白
核心原因分析
你的代码中旋转时的位移计算存在错误,导致图片被绘制到了PictureRecorder的可视区域之外,最终生成空白图片。纯Flutter App可能因渲染上下文的差异未触发这个问题,但集成到iOS原生项目时,渲染裁剪逻辑更严格,错误直接显现。
具体错误点:
r的计算逻辑错误:原代码用sqrt(image.width * image.height + image.height * image.width) / 2,等价于sqrt(2*width*height)/2,并非图片对角线一半的正确计算方式(正确应为sqrt(image.width² + image.height²)/2)。- 旋转位移逻辑复杂且偏差,导致图片绘制位置完全超出录制范围。
解决方案
1. 修正旋转绘制逻辑
简化旋转位移计算,确保图片始终在PictureRecorder的可视区域内:
import 'dart:ui' as ui; import 'package:flutter/widgets.dart'; import 'dart:math'; Future<ui.Image> rotatedImage({required ui.Image image, required double angle}) async { final pictureRecorder = ui.PictureRecorder(); final canvas = Canvas(pictureRecorder); // 计算旋转后的目标画布尺寸(90/270度旋转时宽高互换) final int targetWidth = angle.abs() == pi / 2 ? image.height : image.width; final int targetHeight = angle.abs() == pi / 2 ? image.width : image.height; canvas.save(); // 1. 将画布原点移到目标画布中心 canvas.translate(targetWidth / 2, targetHeight / 2); // 2. 执行旋转操作 canvas.rotate(angle); // 3. 将图片绘制到以原点为中心的位置(偏移量为负的图片宽高一半) canvas.drawImage(image, Offset(-image.width / 2, -image.height / 2), Paint()); canvas.restore(); final picture = pictureRecorder.endRecording(); return await picture.toImage(targetWidth, targetHeight); }
2. 确保在Flutter UI线程执行绘制
集成模式下,若代码由原生触发,可能运行在非UI线程,导致toImage无法正确渲染。需通过WidgetsBinding确保操作在UI线程执行:
Future<ui.Image> rotatedImage({required ui.Image image, required double angle}) async { final completer = Completer<ui.Image>(); WidgetsBinding.instance.addPostFrameCallback((_) async { final pictureRecorder = ui.PictureRecorder(); final canvas = Canvas(pictureRecorder); final targetWidth = angle.abs() == pi / 2 ? image.height : image.width; final targetHeight = angle.abs() == pi / 2 ? image.width : image.height; canvas.save(); canvas.translate(targetWidth / 2, targetHeight / 2); canvas.rotate(angle); canvas.drawImage(image, Offset(-image.width / 2, -image.height / 2), Paint()); canvas.restore(); final picture = pictureRecorder.endRecording(); final result = await picture.toImage(targetWidth, targetHeight); completer.complete(result); }); return completer.future; }
3. 优化网络图片获取(可选)
替换原getNetworkImage方法为更可靠的实现,避免集成模式下的图片上下文兼容问题:
import 'dart:typed_data'; import 'dart:io'; Future<ui.Image> getNetworkImage(String url) async { final httpClient = HttpClient(); final request = await httpClient.getUrl(Uri.parse(url)); final response = await request.close(); final bytes = await consolidateHttpClientResponseBytes(response); final codec = await ui.instantiateImageCodec(bytes); final frameInfo = await codec.getNextFrame(); return frameInfo.image; }
验证步骤
- 替换
rotatedImage函数为修正后的代码 - 确保所有Flutter UI相关操作在UI线程执行
- 重新编译iOS集成项目,测试旋转图片功能
内容的提问来源于stack exchange,提问作者Khang Hồ
相关产品推荐
相关产品推荐

