uniapp H5生成画布,插入网络图片。下载画布

因为网络图片不能直接使用ctx.drawImage()插入。得使用uni.getImageInfo()方法下载后插入。
但是当画布中存在多张网络图片时,必须等待uni.getImageInfo()下载完成后才行。这样得下载套下载。太过于繁琐。所以定义了一个递归下载方法。同时避免下载图片异步,画布不显示的结果。

 

一、引用函数

/**
 * canvas文本自动换行,注意调用前要设置字体,例如: ctx.font = '12px Arial'
 * @param {*} ctx CanvasRenderingContext2D
 * @param {*} text  文本
 * @param {*} x 
 * @param {*} y 
 * @param {*} lw 所占宽度
 * @param {*} lh 行高
 * return 绘制文本所需的高度
 */
const fillTextLineBreak = (ctx, text, x, y, lw, lh, color = '#000', font = '14') => {
	var i = 0;
	var n = 0;
	var r = -1;
	var initHeight = 0;
	ctx.font = "" + font + "px Arial"; //字体大小
	ctx.fillStyle = color; //字体颜色
	while (i < text.length) {
		while (ctx.measureText(text.substring(n, i)).width < lw && i < text.length) {
			i++
		}
		r++
		ctx.fillText(text.substring(n, i), x, y + lh * r)
		n = i
	}
	initHeight = lh * r;
	wx.setStorageSync('initHeight', initHeight);
}


/**
 * 自定义函数roundRect
 * 画圆弧
 * ctx >> 画布
 *bg_x 图片的x坐标
 *bg_y 图片的y坐标
 *bg_w 图片宽度
 *bg_h 图片高度
 *bg_r 图片圆角
 *
 */
function roundRect(ctx, img, bg_x, bg_y, bg_w, bg_h, bg_r) {
	// 开始绘制
	ctx.save();
	ctx.beginPath();
	ctx.arc(bg_x + bg_r, bg_y + bg_r, bg_r, Math.PI, Math.PI * 1.5);
	ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_r, bg_r, Math.PI * 1.5, Math.PI * 2);
	ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_h - bg_r, bg_r, 0, Math.PI * 0.5);
	ctx.arc(bg_x + bg_r, bg_y + bg_h - bg_r, bg_r, Math.PI * 0.5, Math.PI);
	ctx.clip();
	ctx.drawImage(img, bg_x, bg_y, bg_w, bg_h);
	// 恢复之前保存的绘图上下文
	ctx.restore();
}


/*
 * 画布网络图片预处理
 */
function canvasImage(that, Datas = {}, callback = null) {
	var i = Datas.i ? Datas.i : 0;
	var callback_Datas = Datas.callback_Datas ? Datas.callback_Datas : [];
	var data = Datas.data ? Datas.data : [];
	uni.getImageInfo({
		src: data[i],
		success(res) {
			i++;
			callback_Datas.push(res.path)
			if (i == data.length) {
				//回调函数
				if (callback) {
					callback(that, callback_Datas);
					return;
				}
			} else {
                //递归执行下一个上传
				canvasImage(that, {
					i,
					callback_Datas,
					data,
				}, callback);
			}
		},
		fail(e) {
			wx.hideLoading();
			//关闭画布弹窗
			that.posterHideCanvas();
			setTimeout(function() {
				wx.showToast({
					title: '生成失败,稍后再试',
					icon: 'none',
				})
			}, 0)
		}
	});
}

 二、index.vue


			
				
				
				
				
				
			
		

三、index.js

	data() {
		return {
			posterDatas: {
				width: 285, //画布宽度
				height: 406, //画布高度
				buttonType: 1,
				hidden: false, // 是否隐藏海报弹窗
				success: false, // 是否成功生成过海报
			},
			canvasId: 'firstCanvas',
			canvasStyle: 'width: 285px; height: 406px;', // 根据实际需要设置 canvas 的宽高
		};
	},
    
    	//海报生成配置
		posterSetCanvas() {
			var that = this
			var posterDatas = that.posterDatas;
			var tempConfig = that.tempConfig;
			//展示海报弹窗
			that.posterDatas.hidden = true;
			util.showLoading('生成中');
			var userInfo = wx.getStorageSync('userInfo') || {};

			var Datas = {};
			Datas.i = 0;
			Datas.callback_Datas = [];
			Datas.data = [];
			Datas.data[0] = userInfo.touimg; //头像
			Datas.data[1] = app.globalData.swtCircle + "/mp_ewm_v2.php?act=getwxacode&tjrhao=" + (userInfo
				.tjrhao || '') + "&url=pages/home/home"; //小程序码
			util.canvasImage(that, Datas, function(that, canvasImage_arr) {
				//要延时执行的代码
				setTimeout(function() {
					//预处理画布网络地址图片
					var ctx = uni.createCanvasContext(that.canvasId, that);
					// 清除背景
					//ctx.clearRect(0, 0, posterDatas.width, posterDatas.height);
					// 绘制背景
					// ctx.fillStyle = "#fff";
					// ctx.fillRect(0, 0, posterDatas.width, posterDatas.height);
					var bgImg = '/static/images/yao_bj.png';
					// 绘制背景图
					ctx.drawImage(bgImg, 0, 0, posterDatas.width, posterDatas.height);

					//简介
					util.fillTextLineBreak(ctx, "邀请您使用" + tempConfig.appMain.name + "小程序", 100, 81, 150,
						20, '#fff',
						13);
					//标题文字
					ctx.font = "bold 18px PingFang SC";
					ctx.fillStyle = "#fff";
					ctx.textAlign = "start";
					ctx.fillText(userInfo.nickName_hai, 100, 60);

					util.roundRect(ctx, canvasImage_arr[0], 30, 35, 56, 56, 28);

					ctx.font = "bold 18px PingFang SC";
					ctx.fillStyle = "#0D7239";
					ctx.textAlign = "start";
					ctx.fillText('分享有礼 荐者有份', 70, 170);

					ctx.drawImage(canvasImage_arr[1], 65, 200, 160, 160);
					ctx.draw();
					wx.hideLoading();

				}, 200)
			});
		},

		//海报下载图片
		posterDownImage: function() {
			var that = this
			util.showLoading('保存中');
			var posterDatas = that.posterDatas
			uni.canvasToTempFilePath({
				canvasId: "firstCanvas",
				success(res) {
					console.log(res)
					wx.showToast({
						icon: 'none',
						title: '已保存到相册,快去分享吧',
					})
					posterDatas["buttonType"] = 2;
					that.posterDatas = posterDatas;

					// 在 h5 中,res.tempFilePath 返回的是 base64 类型要处理,通过 a 标签的形式下载
					var arr = res.tempFilePath.split(',');
					var bytes = atob(arr[1]);
					let ab = new ArrayBuffer(bytes.length);
					let ia = new Uint8Array(ab);
					for (let i = 0; i < bytes.length; i++) {
						ia[i] = bytes.charCodeAt(i);
					}
					var blob = new Blob([ab], {
						type: 'application/octet-stream'
					});
					var url = URL.createObjectURL(blob);
					var a = document.createElement('a');
					a.href = url;
					a.download = new Date().valueOf() + ".png";
					var e = document.createEvent('MouseEvents');
					e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false,
						false, 0, null);
					a.dispatchEvent(e);
					URL.revokeObjectURL(url);
				},
				fail(e) {
					console.log(e, "fail");
					util.showToast('保存失败,稍后再试”', 'none');
					that.posterHideCanvas();
				}
			})
		},

		//海报隐藏弹窗
		posterHideCanvas: function() {
			var that = this;
			that.posterDatas.buttonType = 1;
			that.posterDatas.hidden = false;
		},

		//海报弹窗禁止屏幕滚动
		posterTouchMove: function() {
			//在蒙层加上 catchtouchmove 事件
			//这里什么都不要放
		},

四、最终结果
uniapp H5生成画布,插入网络图片。下载画布_第1张图片

你可能感兴趣的:(uni-app,前端)