如何在 Flutter 中从 canvas 裁剪圆形(或方形或六边形)区域
How to crop circular(or Square or Hexagon ) area from canvas in Flutter
我想裁剪一个矩形 图像文件 并将其制作成圆形、正方形或六边形,然后 将其保存为本地图像文件.我有一个位图,我想从这个位图中裁剪一个圆形或六边形区域。圆圈外的所有像素都应该是透明的。我该怎么做?
我在android平台发现了类似的问题。 但无法找到真正帮助或指导我在 flutter 中实现此目标的好资源。请与我分享实现此结果的想法。
您可以使用 simple_image_crop 包。
使用 Clipper 裁剪图片
使用 ClipRRect、ClipOval,您还可以使用自定义 Clipper 为图像提供自定义形状
检查这个 link https://www.woolha.com/tutorials/flutter-using-clipper-examples
new ClipRRect(
borderRadius: new BorderRadius.circular(8.0),
child: your image child,
)
这些简单的步骤得到了所需的结果。
- 创建一个PictureRecorder。
- 用你的 PictureRecorder.
创建 Canvas
- 使用 canvas.drawCircle() 在 canvas 中画圆。
- 在 PictureRecorder 上调用 endRecording() 以获取图片。
- 在图片上调用 toImage()。
- 转换图像 toByteData() 。
- 使用 getApplicationDocumentsDirectory()本地 保存图像。
Canvas 屏幕
已将图像 Canvas 保存为 png
完整源代码:
import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'package:flutter/services.dart' show rootBundle;
import 'dart:async';
import 'dart:typed_data';
import 'dart:math' as math;
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
class CustomImageCanvas extends StatefulWidget {
CustomImageCanvas({Key key, this.title}) : super(key: key);
final String title;
@override
_CustomImageCanvasState createState() => _CustomImageCanvasState();
}
class _CustomImageCanvasState extends State<CustomImageCanvas> {
ui.Image image;
bool isImageloaded = false;
void initState() {
super.initState();
init();
}
Future<Null> init() async {
final ByteData data = await rootBundle.load('assets/image.jpeg');
image = await loadImage(Uint8List.view(data.buffer));
}
Future<ui.Image> loadImage(List<int> img) async {
final Completer<ui.Image> completer = Completer();
ui.decodeImageFromList(img, (ui.Image img) {
setState(() {
isImageloaded = true;
});
return completer.complete(img);
});
return completer.future;
}
Widget _buildImage() {
if (this.isImageloaded) {
return CustomPaint(
painter: PngImagePainter(image: image),
);
} else {
return Center(child: Text('loading'));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
child: _buildImage(),
));
}
}
class PngImagePainter extends CustomPainter {
PngImagePainter({
this.image,
});
ui.Image image;
@override
void paint(Canvas canvas, Size size) {
_drawCanvas(size, canvas);
_saveCanvas(size);
}
Canvas _drawCanvas(Size size, Canvas canvas) {
final center = Offset(150, 50);
final radius = math.min(size.width, size.height) / 8;
// The circle should be paint before or it will be hidden by the path
Paint paintCircle = Paint()..color = Colors.black;
Paint paintBorder = Paint()
..color = Colors.white
..strokeWidth = size.width / 36
..style = PaintingStyle.stroke;
canvas.drawCircle(center, radius, paintCircle);
canvas.drawCircle(center, radius, paintBorder);
double drawImageWidth = 0;
var drawImageHeight = -size.height * 0.8;
Path path = Path()
..addOval(Rect.fromLTWH(drawImageWidth, drawImageHeight,
image.width.toDouble(), image.height.toDouble()));
canvas.clipPath(path);
canvas.drawImage(image, Offset(drawImageWidth, drawImageHeight), Paint());
return canvas;
}
_saveCanvas(Size size) async {
var pictureRecorder = ui.PictureRecorder();
var canvas = Canvas(pictureRecorder);
var paint = Paint();
paint.isAntiAlias = true;
_drawCanvas(size, canvas);
var pic = pictureRecorder.endRecording();
ui.Image img = await pic.toImage(image.width, image.height);
var byteData = await img.toByteData(format: ui.ImageByteFormat.png);
var buffer = byteData.buffer.asUint8List();
// var response = await get(imgUrl);
var documentDirectory = await getApplicationDocumentsDirectory();
File file = File(join(documentDirectory.path,
'${DateTime.now().toUtc().toIso8601String()}.png'));
file.writeAsBytesSync(buffer);
print(file.path);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
我想裁剪一个矩形 图像文件 并将其制作成圆形、正方形或六边形,然后 将其保存为本地图像文件.我有一个位图,我想从这个位图中裁剪一个圆形或六边形区域。圆圈外的所有像素都应该是透明的。我该怎么做?
我在android平台发现了类似的问题。 但无法找到真正帮助或指导我在 flutter 中实现此目标的好资源。请与我分享实现此结果的想法。
您可以使用 simple_image_crop 包。
使用 Clipper 裁剪图片 使用 ClipRRect、ClipOval,您还可以使用自定义 Clipper 为图像提供自定义形状 检查这个 link https://www.woolha.com/tutorials/flutter-using-clipper-examples
new ClipRRect(
borderRadius: new BorderRadius.circular(8.0),
child: your image child,
)
这些简单的步骤得到了所需的结果。
- 创建一个PictureRecorder。
- 用你的 PictureRecorder. 创建 Canvas
- 使用 canvas.drawCircle() 在 canvas 中画圆。
- 在 PictureRecorder 上调用 endRecording() 以获取图片。
- 在图片上调用 toImage()。
- 转换图像 toByteData() 。
- 使用 getApplicationDocumentsDirectory()本地 保存图像。
Canvas 屏幕
已将图像 Canvas 保存为 png
完整源代码:
import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'package:flutter/services.dart' show rootBundle;
import 'dart:async';
import 'dart:typed_data';
import 'dart:math' as math;
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
class CustomImageCanvas extends StatefulWidget {
CustomImageCanvas({Key key, this.title}) : super(key: key);
final String title;
@override
_CustomImageCanvasState createState() => _CustomImageCanvasState();
}
class _CustomImageCanvasState extends State<CustomImageCanvas> {
ui.Image image;
bool isImageloaded = false;
void initState() {
super.initState();
init();
}
Future<Null> init() async {
final ByteData data = await rootBundle.load('assets/image.jpeg');
image = await loadImage(Uint8List.view(data.buffer));
}
Future<ui.Image> loadImage(List<int> img) async {
final Completer<ui.Image> completer = Completer();
ui.decodeImageFromList(img, (ui.Image img) {
setState(() {
isImageloaded = true;
});
return completer.complete(img);
});
return completer.future;
}
Widget _buildImage() {
if (this.isImageloaded) {
return CustomPaint(
painter: PngImagePainter(image: image),
);
} else {
return Center(child: Text('loading'));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
child: _buildImage(),
));
}
}
class PngImagePainter extends CustomPainter {
PngImagePainter({
this.image,
});
ui.Image image;
@override
void paint(Canvas canvas, Size size) {
_drawCanvas(size, canvas);
_saveCanvas(size);
}
Canvas _drawCanvas(Size size, Canvas canvas) {
final center = Offset(150, 50);
final radius = math.min(size.width, size.height) / 8;
// The circle should be paint before or it will be hidden by the path
Paint paintCircle = Paint()..color = Colors.black;
Paint paintBorder = Paint()
..color = Colors.white
..strokeWidth = size.width / 36
..style = PaintingStyle.stroke;
canvas.drawCircle(center, radius, paintCircle);
canvas.drawCircle(center, radius, paintBorder);
double drawImageWidth = 0;
var drawImageHeight = -size.height * 0.8;
Path path = Path()
..addOval(Rect.fromLTWH(drawImageWidth, drawImageHeight,
image.width.toDouble(), image.height.toDouble()));
canvas.clipPath(path);
canvas.drawImage(image, Offset(drawImageWidth, drawImageHeight), Paint());
return canvas;
}
_saveCanvas(Size size) async {
var pictureRecorder = ui.PictureRecorder();
var canvas = Canvas(pictureRecorder);
var paint = Paint();
paint.isAntiAlias = true;
_drawCanvas(size, canvas);
var pic = pictureRecorder.endRecording();
ui.Image img = await pic.toImage(image.width, image.height);
var byteData = await img.toByteData(format: ui.ImageByteFormat.png);
var buffer = byteData.buffer.asUint8List();
// var response = await get(imgUrl);
var documentDirectory = await getApplicationDocumentsDirectory();
File file = File(join(documentDirectory.path,
'${DateTime.now().toUtc().toIso8601String()}.png'));
file.writeAsBytesSync(buffer);
print(file.path);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}