uniapp 微信小程序 canvas绘图海报

微信小程序 太阳码生成分享海报 (此处为公用组件,在需求页面引入即可。其中使用到uview)

在这里插入代码片<template>
	<view class="content">
		<!-- <view class="box"><u-button type="primary" @click="share_qrcode()">生成海报</u-button></view> -->
		<u-mask :show="share_qrcode_flag" @click="share_qrcode_flag = false" :zoom="false" :custom-style="{ background: 'rgba(0,0,0,.8)' }" :duration="0">
			<view class="sq_box">
				<view class="tz_box qrcode_box">
					<!-- <view class="close_box" @click="handleClose"><u-icon name="close" color="#ffffff"></u-icon></view> --> // 关闭按钮(目前是点击遮罩层后关闭页面)
					<view class="share_qrcode">
						<canvas canvas-id="myCanvas" style="width: 690px;height:1040px; position: fixed;top: -10000px;"></canvas>
						<image @longpress="this.showSaveImgWin = true" style="width: 100%; height: 100%;border-radius: 14rpx;" :src="canvasToTempFilePath"></image>
					</view>
				</view>
			</view>
		</u-mask>
		<u-modal
			v-model="showSaveImgWin"
			content="确定要保存图片吗"
			@confirm="saveShareImg(canvasToTempFilePath)"
			@cancel="this.showSaveImgWin = false"
			:show-cancel-button="true"
		></u-modal>
	</view>
</template>

<script>
export default {

	data() {
		return {
			ratio: 1,
			ctx: null, // 创建canvas对象
			canvasToTempFilePath: null, // 保存最终生成的导出的图片地址
			openStatus: true, // 声明一个全局变量判断是否授权保存到相册
			share_qrcode_flag: false,
			showSaveImgWin: false, //保存图片到相册
			userInfo:"",
			option: {
				//绘制海报内容
				codeUrl: "", //小程序太阳码
				coverUrl: 'https://pic1.zhimg.com/80/v2-2714df42147132464a71af391ed04be4_720w.jpg', //题库图片
				headUrl: 'https://pic1.zhimg.com/80/v2-b9df1fdfe67f2177d5c84af90dcadfc1_720w.jpg?source=1940ef5c', //头像
				bgUrl: 'https://pic3.zhimg.com/v2-8fbde0f9ac6a19a23aa839e73394618a_b.jpg', //图片背景填充,和 fillStyle 只能传一个,bgUrl 优先级高于 fillStyle
				fillStyle: '#0688ff', //纯色背景填充颜色
			}
		};
	},

	mounted() {
	// 父组件传递给子组件事件
		uni.$off("team_code").$on("team_code",value => {
			this.option.codeUrl = value.url
			this.userInfo = value.info
			this.share_qrcode()
		})
	},
	methods: {
		share_qrcode() {
			if (!this.canvasToTempFilePath) {
				this.createCanvasImage(this.option);
			}
			this.share_qrcode_flag = true;
		},
		handleClose(){
			this.share_qrcode_flag = false
			uni.hideLoading()
		},
		//获取图片信息
		downloadFileImg(url) {
			return new Promise(resolve => {
				uni.getImageInfo({
					src: url,
					success: res => {
						resolve(res.path);
					},
					fail: err => {
						console.log(err);
						uni.showToast({
							title: '网络错误请重试',
							icon: 'loading'
						});
					}
				});
			});
		},
		// 生成海报
		async createCanvasImage(option) {
			// 点击生成海报数据埋点
			if (!this.ctx) {
				uni.showLoading({
					title: '生成中...'
				});
				let code = this.downloadFileImg(this.option.codeUrl);
				let cover = this.downloadFileImg(option.coverUrl);
				let headImg = this.downloadFileImg(this.userInfo.avatarUrl);
				let bgUrl = '../../static/personal/icon-team_bg.png';
				
				Promise.all([headImg, code, cover, bgUrl]).then(result => {
					const ctx = uni.createCanvasContext('myCanvas', this);
					let canvasWidthPx = 750 * this.ratio,
						canvasHeightPx = 1040 * this.ratio,
						avatarurl_width = 140, //绘制的头像宽度
						avatarurl_heigth = 140, //绘制的头像高度
						avatarurl_x = 280, //绘制的头像在画布上的位置
						avatarurl_y = 50, //绘制的头像在画布上的位置
						codeurl_width = 300, //绘制的二维码宽度
						codeurl_heigth = 300, //绘制的二维码高度
						codeurl_x = 195, //绘制的二维码在画布上的位置
						codeurl_y = 300, //绘制的二维码在画布上的位置
						coverurl_width = 0, //绘制的封面宽度
						coverurl_heigth = 0, //绘制的封面高度
						coverurl_x = 0, //绘制的封面在画布上的位置
						coverurl_y = 0; //绘制的封面在画布上的位置
						
					if (option.bgUrl) {
						ctx.drawImage(result[3], 0, 0, 690, 1040); // 背景图片需要本地
					} else {
						//绘制圆角矩形
						ctx.save();
						ctx.translate(0, 0);
						//绘制圆角矩形的各个边
						this.drawRoundRectPath(ctx, 690, 1040, 14);
						ctx.fillStyle = option.fillStyle || '#0688ff'; //若是给定了值就用给定的值否则给予默认值
						ctx.fill();
						ctx.restore();
					}

					ctx.save(); // 先保存状态 已便于画完圆再用
					ctx.beginPath(); //开始绘制
					//先画个圆   前两个参数确定了圆心 (x,y) 坐标  第三个参数是圆的半径  四参数是绘图方向  默认是false,即顺时针
					ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);
					ctx.clip(); //画了圆 再剪切  原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
					ctx.drawImage(result[0], avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片

					ctx.restore(); //恢复之前保存的绘图上下文状态 可以继续绘制

					ctx.font = 'normal bold 28px sans-serif';
					ctx.setFillStyle('#171717'); // 文字颜色
					ctx.textAlign = 'center' // 文字居中显示
					ctx.fillText(this.userInfo.nickName,355,230)
					ctx.drawImage(result[1], codeurl_x, codeurl_y, codeurl_width, codeurl_heigth); // 绘制二维码
					
					ctx.fillText("扫码加入", 355, 660); // 绘制文字
					
					ctx.fillText(this.userInfo.company_name, 355, 720); // 绘制文字
					
					ctx.fillText("长按图片,可保存到相册", 355, 780); // 绘制文字

					ctx.drawImage(result[2], coverurl_x, coverurl_y, coverurl_width, coverurl_heigth); // 绘制封面
					ctx.draw(false, () => {
						// canvas画布转成图片并返回图片地址
						uni.canvasToTempFilePath(
							{
								canvasId: 'myCanvas',
								success: res => {
									this.canvasToTempFilePath = res.tempFilePath;
									this.showShareImg = true;
									uni.showToast({
										title: '绘制成功'
									});
								},
								fail: err => {
									uni.showToast({
										title: '绘制失败'
									});
								},
								complete: () => {
									uni.hideLoading();
									uni.hideToast();
								}
							},
							this
						);
					});
				});
			}
		},

		drawRoundRectPath(cxt, width, height, radius) {
			cxt.beginPath(0);
			//从右下角顺时针绘制,弧度从0到1/2PI
			cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);

			//矩形下边线
			cxt.lineTo(radius, height);

			//左下角圆弧,弧度从1/2PI到PI
			cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);

			//矩形左边线
			cxt.lineTo(0, radius);

			//左上角圆弧,弧度从PI到3/2PI
			cxt.arc(radius, radius, radius, Math.PI, (Math.PI * 3) / 2);

			//上边线
			cxt.lineTo(width - radius, 0);

			//右上角圆弧
			cxt.arc(width - radius, radius, radius, (Math.PI * 3) / 2, Math.PI * 2);

			//右边线
			cxt.lineTo(width, height - radius);
			cxt.closePath();
		},

		// 保存到系统相册
		saveShareImg(canvasToTempFilePath) {
			uni.saveImageToPhotosAlbum({
				filePath: canvasToTempFilePath,
				success: () => {
					this.$u.toast('保存成功,快去分享到朋友圈吧~');
				},
				fail: () => {
					this.$u.toast('保存失败~');
				}
			});
		}
	}
};
</script>

<style lang="scss">
.sq_box {
	display: flex;
	height: 100%;
	justify-content: center;
	align-items: center;
	color: #333333;
	padding:0 60rpx ;
	.tz_box {
		border-radius: 14rpx;
		padding: 40rpx;
		display: flex;
		flex-direction: column;
		align-items: center;
		position: relative;
		width: 100%;
		text-align: center;
		line-height: 50rpx;
		height: 970rpx;
		.close_box {
			position: absolute;
			left: 50%;
			bottom: -100rpx;
			border: 4rpx solid #ffffff;
			width: 60rpx;
			height: 60rpx;
			margin-left: -30rpx;
			border-radius: 50%;
			display: flex;
			justify-content: center;
			align-items: center;
		}
		.share_qrcode {
			width: 100%;
			height: 100%;
		}
		.tz_title {
			font-size: 34rpx;
			font-weight: 600;
		}

		.content_box {
			margin: 50rpx 0;
			text-align: left;
			.inf {
				font-weight: bold;
				font-size: 36rpx;
				.copy {
					font-weight: 0;
					color: rgb(85, 104, 147);
					font-size: 30rpx;
				}
			}
		}
	}
	.qrcode_box {
		padding: 0;
	}
}
</style>

不喜勿喷,简单记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值