公司有个需求是需要生成二维码的,查询了很多资料,一开始打算用切图的形式来完成图片的拼接,然后再利用RepaintBoundary生成图片,但是这样每个手机生成的图片大小是不一样的,所以就需要利用canvans来实现了,效果如下图
991617678483_.pic.jpg
下面是代码
String bgImageS = 'lib/images/product_bg.png';
UI.Image bgImage = await Tools.byteToImage(bgImageS, false, bgImageS);
UI.Image headerImage = await Tools.byteToImage(
Tools.getImgUrl(personInfoProvider.headImage),
true,
'lib/images/defaultHead.png');
Paint paint = Paint()
..filterQuality = FilterQuality.high // 创建一个画笔并配置其属性
..strokeWidth = 1 // 画笔的宽度
..isAntiAlias = true // 是否抗锯齿
..color = Colors.white; // 画笔颜色
UI.PictureRecorder pictureRecorder = new UI.PictureRecorder(); // 图片记录仪
Canvas canvas = new Canvas(pictureRecorder); //canvas接受一个图片记录仪
double pixelRatio = 2.5; //ScreenUtil.pixelRatio;
// 绘制图片
canvas.drawImageRect(
bgImage,
Rect.fromLTWH(
0, 0, bgImage.width.toDouble(), bgImage.height.toDouble()),
Rect.fromLTWH(
0, 0, bgImage.width * pixelRatio, bgImage.height * pixelRatio),
paint); // 直接画图
//第二个 ui.Image对象 由pictureRecorder结束记录后返回 toImage裁剪图片
//头像
canvas.save();
canvas.clipRRect(RRect.fromRectAndRadius(
Rect.fromLTWH(259 * pixelRatio, 62 * pixelRatio, 102 * pixelRatio,
102 * pixelRatio),
Radius.circular(51*pixelRatio)));
Size headerImageSize =
Size(headerImage.width.toDouble(), headerImage.height.toDouble());
Rect headerImageDstRect = Rect.fromLTWH(259 * pixelRatio, 62 * pixelRatio,
102 * pixelRatio, 102 * pixelRatio);
// 根据适配模式,计算适合的缩放尺寸8
FittedSizes headerImageFittedSizes =
applyBoxFit(BoxFit.contain, headerImageSize, headerImageDstRect.size);
// 获得一个图片区域中,指定大小的,居中位置处的 Rect
Rect headerImageInputRect = Alignment.center.inscribe(
headerImageFittedSizes.source, Offset.zero & headerImageSize);
// 获得一个绘制区域内,指定大小的,居中位置处的 Rect
Rect headerImageOutputRect = Alignment.center
.inscribe(headerImageFittedSizes.destination, headerImageDstRect);
canvas.drawImageRect(
headerImage,
headerImageInputRect,
Rect.fromLTWH(258 * pixelRatio, 60 * pixelRatio, 105 * pixelRatio,
105 * pixelRatio),
paint);
canvas.restore();
//店铺文字
UI.ParagraphBuilder shopNameBuilder = UI.ParagraphBuilder(
UI.ParagraphStyle(
textAlign: TextAlign.center,
fontSize: 30.0 * pixelRatio,
textDirection: TextDirection.ltr,
maxLines: 1,
),
)
..pushStyle(
UI.TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
textBaseline: UI.TextBaseline.alphabetic),
)
..addText(personInfoProvider.shopName);
UI.Paragraph shopNameParagraph = shopNameBuilder.build()
..layout(UI.ParagraphConstraints(
width: 620.0 * pixelRatio - 35 * 2 * pixelRatio));
canvas.drawParagraph(
shopNameParagraph, Offset(35 * pixelRatio, 190.0 * pixelRatio));
double goodsImageTop;
double priceTop;
String goodsName = goodsNames[I];
TextPainter goodsNameTextPainter;
double goodsNameTop;
double qrTop;
goodsImageTop = 255 * pixelRatio;
priceTop = 800 * pixelRatio;
goodsName = goodsNames[I];
goodsNameTextPainter = Tools.calculateTextSize(
context,
goodsName,
30.0 * pixelRatio,
FontWeight.normal,
(620.0 - 60 * 2) / 2 * pixelRatio,
2);
goodsNameTop =
goodsNameTextPainter.width < ((620.0 - 60 * 2) / 2) * pixelRatio
? 800 * pixelRatio
: 785 * pixelRatio;
qrTop = 908 * pixelRatio;
//主图
String goodsImageName = goodsImageNames[I];
UI.Image goodsImage = await Tools.byteToImage(
Tools.getImgUrl(goodsImageName), true, 'lib/images/account_bg.png');
Size goodsImageSize =
Size(goodsImage.width.toDouble(), goodsImage.height.toDouble());
Rect goodsImageDstRect = Rect.fromLTWH(
35 * pixelRatio, goodsImageTop, 550 * pixelRatio, 500 * pixelRatio);
// 根据适配模式,计算适合的缩放尺寸
FittedSizes goodsImageFittedSizes =
applyBoxFit(BoxFit.contain, goodsImageSize, goodsImageDstRect.size);
// 获得一个图片区域中,指定大小的,居中位置处的 Rect
Rect goodsImageInputRect = Alignment.center.inscribe(
goodsImageFittedSizes.source, Offset.zero & goodsImageSize);
// 获得一个绘制区域内,指定大小的,居中位置处的 Rect
Rect goodsImageOutputRect = Alignment.center
.inscribe(goodsImageFittedSizes.destination, goodsImageDstRect);
canvas.drawImageRect(
goodsImage, goodsImageInputRect, goodsImageOutputRect, paint);
//商品名称
UI.ParagraphBuilder goodsNameParagraphBuilder = UI.ParagraphBuilder(
UI.ParagraphStyle(
textAlign: TextAlign.left,
fontSize: 30.0 * pixelRatio,
textDirection: TextDirection.ltr,
maxLines: 2,
),
)
..pushStyle(UI.TextStyle(
color: Colors.black, textBaseline: TextBaseline.alphabetic))
..addText(goodsName);
UI.Paragraph goodsNameParagraph = goodsNameParagraphBuilder.build()
..layout(UI.ParagraphConstraints(
width: (620.0 - 60 * 2) / 2 * pixelRatio));
canvas.drawParagraph(
goodsNameParagraph, Offset(60 * pixelRatio, goodsNameTop));
String disprice = disprices[I];
//价格图标
UI.ParagraphBuilder priceIconParagraphBuilder = UI.ParagraphBuilder(
UI.ParagraphStyle(
textAlign: TextAlign.right,
fontSize: 30.0 * pixelRatio,
textDirection: TextDirection.ltr,
maxLines: 1,
fontWeight: FontWeight.bold,
),
)
..pushStyle(
UI.TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
textBaseline: TextBaseline.alphabetic),
)
..addText('¥');
TextPainter priceTextPainter = Tools.calculateTextSize(
context,
disprice,
40.0 * pixelRatio,
FontWeight.bold,
(620.0 - 60 * 2) / 2 * pixelRatio - 30 * pixelRatio,
1);
UI.Paragraph priceIconParagraph = priceIconParagraphBuilder.build()
..layout(UI.ParagraphConstraints(
width:
(620.0 - 60 * 2) / 2 * pixelRatio - priceTextPainter.width));
canvas.drawParagraph(priceIconParagraph,
Offset((620.0 / 2) * pixelRatio, priceTop + 8 * pixelRatio));
//价格
UI.ParagraphBuilder priceParagraphBuilder = UI.ParagraphBuilder(
UI.ParagraphStyle(
textAlign: TextAlign.right,
fontSize: 40.0 * pixelRatio,
fontWeight: FontWeight.bold,
textDirection: TextDirection.ltr,
maxLines: 1,
),
)
..pushStyle(
UI.TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
textBaseline: TextBaseline.alphabetic),
)
..addText(disprice);
UI.Paragraph priceParagraph = priceParagraphBuilder.build()
..layout(UI.ParagraphConstraints(
width: (620.0 - 60 * 2) / 2 * pixelRatio - 30 * pixelRatio));
canvas.drawParagraph(priceParagraph,
Offset((620.0 / 2) * pixelRatio + 30 * pixelRatio, priceTop));
//二维码
UI.Image qrImage = await Tools.toQrImageData(shareUrl);
canvas.drawImageRect(
qrImage,
Rect.fromLTWH(
0, 0, qrImage.width.toDouble(), qrImage.height.toDouble()),
Rect.fromLTWH(
60 * pixelRatio, qrTop, 100 * pixelRatio, 100 * pixelRatio),
paint);
}
double bgImageH;
bgImageH = 1069 * pixelRatio;
UI.Image picture = await pictureRecorder
.endRecording()
.toImage((620 * pixelRatio).toInt(), bgImageH.toInt()); //设置生成图片的宽和高
//ByteData对象 转成 Uint8List对象 给 Image.memory() 使用来显示
ByteData pngImageBytes =
await picture.toByteData(format: UI.ImageByteFormat.png);
有问题欢迎留言