公司有個需求是需要生成二維碼的,查詢了很多資料,一開始打算用切圖的形式來完成圖片的拼接,然后再利用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 // 創(chuàng)建一個畫筆并配置其屬性
..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);
// 獲得一個圖片區(qū)域中钉凌,指定大小的,居中位置處的 Rect
Rect headerImageInputRect = Alignment.center.inscribe(
headerImageFittedSizes.source, Offset.zero & headerImageSize);
// 獲得一個繪制區(qū)域內捂人,指定大小的御雕,居中位置處的 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);
// 獲得一個圖片區(qū)域中,指定大小的饮笛,居中位置處的 Rect
Rect goodsImageInputRect = Alignment.center.inscribe(
goodsImageFittedSizes.source, Offset.zero & goodsImageSize);
// 獲得一個繪制區(qū)域內咨察,指定大小的,居中位置處的 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);
有問題歡迎留言