小程序canvas画海报,并保存本地

226 阅读2分钟

{ this.$nextTick(async () => { // 初始化 wx.createSelectorQuery() .select('#shareCanvas') // 在 WXML 中填入的 id .fields({ node: true, size: true }) .exec((res) => {

									let unit = _this.unit * 5
									// Canvas 对象
									const canvas = res[0].node
									canvas.width = unit * 325
									canvas.height = unit * 450
									// 渲染上下文
									const ctx = canvas.getContext('2d')


									// 画图片
									_this.fillRoundRectImage(ctx, canvas,
											'https://lingyue-surveypanda.oss-cn-hangzhou.aliyuncs.com/miniProgram/template/poster3.png',
											0, 0, unit * 325, unit * 450, 10)
										.then(() => {
											_this.fillRectImage(ctx, canvas,
												'https://lingyue-surveypanda.oss-cn-hangzhou.aliyuncs.com/miniProgram/template/whitemarshalling.png',
												unit * 30, unit * 30, unit * 106,
												unit * 26).then(() => {

												// 头像
												_this.fillRoundRectImage(ctx,
														canvas, this.imageURL,
														unit * 26, unit * 375,
														unit * 36, unit * 36,
														30
													)
													.then(() => {

														// 问卷名称   

														_this.fillText({
															ctx: ctx,
															x: unit *
																26,
															y: unit *
																120,
															font: parseInt(
																	18 *
																	unit
																) +
																"px bold",
															fillStyle: "#fff",
															text: this
																.title,
															maxWidth: 273 *
																unit,
															maxLine: 3
														})
														// 昵称

														_this.fillText({
															ctx: ctx,
															x: unit *
																72,
															y: unit *
																390,
															font: parseInt(
																	14 *
																	unit
																) +
																"px bold",
															fillStyle: "#fff",
															text: this
																.WXusername,
														})

														// 
														ctx.fillStyle =
															"#fff"
														ctx.font =
															parseInt(
																12 * unit
															) +
															"px bold";
														ctx.fillText(
															'邀请你来助力填写',
															unit * 72,
															unit * 410)
														_this
															.fillRoundRectImage(
																ctx,
																canvas,
																this
																.reshttp,
																unit * 232,
																unit * 354,
																unit * 75,
																unit * 75,
																30)
															.then(() => {


																wx.canvasToTempFilePath({
																	canvas: canvas,
																	success(
																		res
																	) {
																		//
																		_this
																			.res =
																			res
																	}
																})
															})
													})
											})
										})
								})
						})
					}
				}
			});
		},
		/**
		 * @param {Object} option
		 * ctx
		 */
		fillText(option) {
			return new Promise((resolve, reject) => {
				if (!option.text) {
					resolve()
					return
				}
				let ctx = option.ctx
				if (option.font) {
					ctx.font = option.font;
				}

				if (option.fillStyle) {
					ctx.fillStyle = option.fillStyle;
				}
				if (option.maxWidth) {

					let measureText = ctx.measureText(option.text);
					let textWidth = measureText.width
					let textHeight = measureText.fontBoundingBoxAscent + measureText.fontBoundingBoxDescent;
					if (textWidth > option.maxWidth) {
						let text = ''
						let line = 1;
						for (let i = 0; i < option.text.length; i++) {
							text += option.text[i]
							textWidth = ctx.measureText(text).width

							// 长度超出
							if (textWidth >= option.maxWidth) {

								// 当前是否最大行最大行

								if (line == option.maxLine) {

									// 最大行要替换...
									text += '...'
									for (let j = 0; j < 5; j++) {
										text = text.substring(0, text.length - 4) + '...'
										textWidth = ctx.measureText(text).width

										// 长度超出
										if (textWidth <= option.maxWidth) {
											break
										}
									}
									ctx.fillText(text, option.x, option.y)
									break
								} else {
									ctx.fillText(text, option.x, option.y)
									option.y += textHeight
								}
								line++
								text = ''
							}
						}
					} else {
						ctx.fillText(option.text, option.x, option.y)
					}
				} else {
					ctx.fillText(option.text, option.x, option.y)
				}
				resolve()

			})
		},
		fillRectImage(ctx, canvas, url, x, y, w, h) {
			return new Promise((resolve, reject) => {
				if (!url) {
					resolve()
					return
				}
				const image = canvas.createImage()
				// 图片加载完成回调
				image.onload = () => {
					ctx.drawImage(image, x, y, w, h)
					resolve()
				}
				// 设置图片src
				image.src = url
			})
		},
		fillRoundRectImage(ctx, canvas, url, x, y, w, h, r) {
			return new Promise((resolve, reject) => {
				if (!url) {
					resolve()
					return
				}
				const image = canvas.createImage()
				// 图片加载完成回调
				image.onload = () => {

					if (w < 2 * r) {
						r = w / 2;
					}
					if (h < 2 * r) {
						r = h / 2;
					}
					// 先保存画布,以防画布上的内容消失
					ctx.save()
					ctx.beginPath();
					ctx.moveTo(x + r, y);
					ctx.lineTo(x + w - r, y);
					ctx.arc(x + w - r, y + r, r, Math.PI / 180 * 270, 0, false);
					ctx.lineTo(x + w, y + h - r);
					ctx.arc(x + w - r, y + h - r, r, 0, Math.PI / 180 * 90, 0, false);
					ctx.lineTo(x + r, y + h);
					ctx.arc(x + r, y + h - r, r, Math.PI / 180 * 90, Math.PI / 180 * 180, false);
					ctx.lineTo(x, y + r);
					ctx.arc(x + r, y + r, r, Math.PI / 180 * 180, Math.PI / 180 * 270, false);
					// 将图片绘制到 canvas 上 
					ctx.closePath();
					ctx.clip()
					ctx.drawImage(image, x, y, w, h)
					ctx.restore()
					resolve()
				}
				// 设置图片src
				image.src = url
			})
		},
		fillRoundRectFull(ctx, canvas, color, x, y, w, h, r) {

			return new Promise((resolve, reject) => {
				// 图片加载完成回调
				if (w < 2 * r) {
					r = w / 2;
				}
				if (h < 2 * r) {
					r = h / 2;
				}
				ctx.restore()
				ctx.beginPath();
				ctx.moveTo(x + r, y);
				ctx.lineTo(x + w - r, y);
				ctx.arc(x + w - r, y + r, r, Math.PI / 180 * 270, 0, false);
				ctx.lineTo(x + w, y + h - r);
				ctx.arc(x + w - r, y + h - r, r, 0, Math.PI / 180 * 90, 0, false);
				ctx.lineTo(x + r, y + h);
				ctx.arc(x + r, y + h - r, r, Math.PI / 180 * 90, Math.PI / 180 * 180, false);
				ctx.lineTo(x, y + r);
				ctx.arc(x + r, y + r, r, Math.PI / 180 * 180, Math.PI / 180 * 270, false);
				// 将图片绘制到 canvas 上  
				ctx.closePath();
				ctx.fillStyle = color;
				ctx.fill();
				resolve()
			})
		},
		positiveBut() {
			var _this = this;
			if (this.res) {
				// 保存图片到相册
				uni.authorize({
					scope: "scope.writePhotosAlbum",
					success() {
						_this.writePhotosAlbum = true;
						uni.saveImageToPhotosAlbum({
							filePath: _this.res.tempFilePath,
							success: function() {
								uni.showToast({
									title: '保存成功',
									icon: 'success',
									duration: 2000
								});
							},
						});
					},
					fail() {
						_this.writePhotosAlbum = false;
					},
				});
			}

		},