uniapp之小程序端生成分享海报(带自定义参数的二维码)

内容需求:

小程序端生成一个海报,海报内容包括当前授权账号的头像,当前授权账号的邀请码,一张特定图片,分享页面的带对应参数的小程序二维码;生成的海报需要保存到本地

功能方法:

1.前端用canvas绘图转为图片

2.传相对应的参数 到后端 ,后端用canvas绘图转为图片传给前端

目前我们的项目是多端小程序,百度小程序和微信小程序,因为两端在实际运行的差异所以微信端使用的是前端生成,百度端使用的是后端生成的方式。

具体流程:

在生成海报之前需要根据海报的内容准备对应的图片和文字内容,这样能更稳定快速的生成海报。

!!注意如果绘图过程中使用的图片是网络图片(非本地图片)需要使用uni.getImageInfo方法对图片进行处理!!

!!

        由于在获取临时路劲保存图片的时候用一倍的canvas保存的图片会很模糊,我们需要对canvas画布进行多倍处理,一般二倍即可,太大了在Android上可能会出现问题 ,我这里使用的是固定倍数3倍

        也可以使用设备的像素比为倍率  

  const res = uni.getSystemInfoSync();
  let  pixelRatio = res.pixelRatio;
    console.log("该设备的像素比",pixelRatio )

!!

!!在开发过程中还有遇到点小麻烦的就是如何生成对应页面并带对应参数的动态二维码呢?

解决方式是由后端请求微信服务接口 通过配置对应的参数就可以生成一个二维码啦,再将二维码发送给前端就可以了。

涉及的文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/qr-code.html(这里有好几种生成二维码的方法,可以根据自己的业务来调用)!!

<template>
    <canvas :style="{height: pupopHeight + 'px',width: pupopWidth + 'px'}" canvas-id="myCanvas"></canvas>
    <uni-popup   ref="popup" type="center">
			<view class="popup-wrap">
				<view class="popup-head">
					生成海报
					<view @click="close_popup()" class="close_icon"></view>
				</view>
				<image :src="posterImg" mode=""></image>
				<view  class="popup-footer">
					<button class="save-btn" @click="saveToLocal()" type="default">保存到相册</button>
					<view class="tips">保存图片到相册,你就可以分享啦!</view>
				</view>
			</view>
    </uni-popup>
</template>

		
<script>
    data(){
        return{
            pupopWidth:590,
			pupopHeight:788,
            //一定要注意像素密度的问题,这里使用的固定数值
            pixelRatio:3,//屏幕像数密度
            inviteQR:'',//动态二维码
            posterImg:',//最后生成的海报
            
        }
    },
    mounted(){
			
			this.pupopWidth = this.pupopWidth*this.pixelRatio
			this.pupopHeight = this.pupopHeight*this.pixelRatio
			console.log("屏幕像素密度",this.pixelRatio,this.pupopWidth,this.pupopHeight)
    },
    methods:{
        //获取当前页面的二维码
        //这里的做法是传对应的参数到后端,后端生成二位的图片返给前端
        
        shareing(){
				uni.showLoading({
					  title:"海报生成中...",
					 mask:true
				})
				
				//#ifdef MP-WEIXIN
                    //这里参数是前端和后端商议好,生成二维码需要前端传那些对应的值,这里我传了当前页面的路径和邀请码及当前页面的参数
					let params={
						page:this.path,
						scene:this.scene
					}
					Api.apiGetCode(params).then(res=>{//去后端请求动态二维码
						if(res.code === 2000){
							this.inviteQR = res.data.qrCodePath
							this.createPoster();
						}
						
					})
               //#endif
        
        },
    //生成海报--微信端
	createPoster(){
	    let _this = this
		_this.headImg = uni.getStorageSync('avatarUrl')//去本地缓存获取头像
		uni.getImageInfo({
			 src:_this.headImg,
			 success(image) {
			const canvasId = "myCanvas"
		    let  ctx = uni.createCanvasContext(canvasId,_this) // 自定义组件中 一定要传this ,这里一开始没加,困惑很久,一定要写一下
			// 填充背景
			ctx.setFillStyle('#FFFFFF')
			ctx.fillRect(0,0,_this.pupopWidth,_this.pupopHeight);
			ctx.save()
								
			// 头像和二维码大小都需要在规定大小的基础上放大像素比的比例后面都会*this.pixelRatio
			let headerW = 48 * _this.pixelRatio
			let headerX = 40 * _this.pixelRatio
			let headerY = 40 * _this.pixelRatio
			// 控制头像为圆形
			ctx.setStrokeStyle('rgba(0,0,0,.2)') //设置线条颜色,如果不设置默认是黑色,头像四周会出现黑边框
			ctx.arc(headerX + headerW / 2, headerY + headerW / 2, headerW / 2, 0, 2 * Math.PI)
			ctx.stroke()
			//画完之后执行clip()方法,否则不会出现圆形效果
			ctx.clip()
			// 将头像画到画布上			
			ctx.drawImage(image.path, headerX, headerY, headerW, headerW)
			ctx.restore()
			ctx.save()
			//绘制邀请码
			const uniqueCode = uni.getStorageSync('uniqueCode') || '';
			// console.log("uniqueCodeuniqueCode",uniqueCode)
			let invateCode = `邀请码:${uniqueCode}`
			let invateCodeX = headerX + headerW + 14 * _this.pixelRatio
			let invateCodeY = headerY + headerW/2 + ((26*_this.pixelRatio)/2)
			ctx.setFontSize(26*_this.pixelRatio);
			ctx.setFillStyle('#333333');
			ctx.fillText(invateCode, invateCodeX, invateCodeY);
			ctx.stroke();
			//生成banner图
			uni.getImageInfo({
					src: _this.banner,//这里的banner是展示的商品图
					success(image) {
					let bannerW = 510 * _this.pixelRatio
					let bannerH = 255 * _this.pixelRatio
					let bannerX = 40 * _this.pixelRatio
					let bannerY = 40 * _this.pixelRatio + headerW + 24* _this.pixelRatio
					// 将banner到画布上
					ctx.drawImage(image.path, bannerX, bannerY, bannerW, bannerH)
					ctx.restore()
					ctx.save()
					//banner 描述
                       
                    //这里会处理多行显示文字,超出显示省略号的效果
					let  bannerTextX = 40 * _this.pixelRatio
					let bannerTextY = bannerY + bannerH + 20 * _this.pixelRatio  + 50*_this.pixelRatio  //这里的y轴起始值是顶上的距离还要特意加上文字的行高
					let chr = _this.bannerText.split("");//这个方法是将一个字符串分割成字符串数组
					let temp = "";
					let row = [];
					ctx.setFontSize(30*_this.pixelRatio)
					ctx.setFillStyle("#333333")
					for (var a = 0; a < chr.length; a++) {
					    if (ctx.measureText(temp).width < 510 * _this.pixelRatio) {
							temp += chr[a];
						}else {
							a--; //这里添加了a-- 是为了防止字符丢失,效果图中有对比
							row.push(temp);
							temp = "";
						}
					}
					row.push(temp); 
					if (row.length > 2) {
						let rowCut = row.slice(0, 2);
						let rowPart = rowCut[1];
						let test = "";
						let empty = [];
						for (var a = 0; a < rowPart.length; a++) {
					        if (ctx.measureText(test).width < 510 * _this.pixelRatio) {
								test += rowPart[a];
						    }else {
							    break;
						    }
						}
					   empty.push(test);
					   var group = empty[0] + "..."//这里只显示两行,超出的用...表示
					   rowCut.splice(1, 1, group);
							row = rowCut;
					}
					for (var b = 0; b < row.length; b++) {
						ctx.fillText(row[b], bannerTextX, bannerTextY + b * 50*_this.pixelRatio, 510 * _this.pixelRatio);
					}
											
											
					//画间隔线
					ctx.moveTo (40 * _this.pixelRatio, bannerTextY + 40 * _this.pixelRatio + 50*_this.pixelRatio);       
                    //设置起点状态
					ctx.lineTo (_this.pupopWidth - 40 * _this.pixelRatio,bannerTextY + 40 * _this.pixelRatio + 50*_this.pixelRatio);       
                    //设置末端状态
					ctx.lineWidth = 1 * _this.pixelRatio;//设置线宽状态
					ctx.strokeStyle = '#EEEEEE' ;  //设置线的颜色状态
					ctx.stroke();
											
					//二维码
					uni.getImageInfo({
						src: _this.inviteQR,
						success(res){
							// 画当前页面的二维码
							const img_x = 40 *_this.pixelRatio
							const img_w = 160*_this.pixelRatio
							const img_y = _this.pupopHeight - img_w - 40*_this.pixelRatio				            
                            ctx.drawImage(res.path,img_x,img_y,img_w,img_w) 
													
							//画提示文字
							const tiptextX = img_x + img_w + 30 * _this.pixelRatio
							const tiptext1Y = img_y + (img_w/2)
							const tiptext2Y = img_y + (img_w/2) + 30 * _this.pixelRatio + 14 * _this.pixelRatio
							const tiptext1 = '移居宝'
							const tiptext2 = '长按识别二维码(微信)'
							ctx.setFontSize(30*_this.pixelRatio)
							ctx.setFillStyle("#333333")
							ctx.fillText(tiptext1, tiptextX, tiptext1Y);
							ctx.stroke();
							ctx.setFontSize(26*_this.pixelRatio)
							ctx.setFillStyle("#666666")
							ctx.fillText(tiptext2, tiptextX, tiptext2Y);
							ctx.stroke();
							ctx.draw(false, () => {
									uni.canvasToTempFilePath({
									width: _this.pupopWidth,
									height: _this.pupopHeight,
									destWidth: _this.pupopWidth,				              
                                    destHeight:_this.pupopHeight,
								    canvasId: canvasId,
								    fileType: 'png',
									quality:1,
									success: function(res) {
										_this.posterImg = res.tempFilePath;//最终将canvas转换为图片
										_this.$refs.popup.open();
										uni.hideLoading()
															
									},
									fail(error) {
										console.log('4',error)
										toast({
										    msg:'生成海报失败,请稍后重试!'
									    })
									    setTimeout(()=>{
										    uni.hideLoading()
									    },2000)
									}
							    },_this)
							})
						},
						fail(error) {
							console.log('获取二维码失败',error)
							toast({
								msg:'生成海报失败,获取二维码失败'
							})
							setTimeout(()=>{
									uni.hideLoading()
							},2000)
						}
					})
				},
				fail(error) {
					console.log('生成商品图失败',error)
					toast({
						msg:'生成海报失败,获取商品图失败'
					})
											
					setTimeout(()=>{
						uni.hideLoading()
					},2000)
											
											
				}
			});
								
		},
		fail(error) {
			console.log('生成头像失败',error)
				toast({
					msg:'生成海报失败,获取头像失败'
				})
				setTimeout(()=>{
					uni.hideLoading()
				},2000)
								 
		}
	})

 },
//将图片保存到本地相册
saveToLocal(){
	//#ifdef MP-WEIXIN
	    uni.saveImageToPhotosAlbum({
			filePath: this.posterImg,
			success: ()=>{
						
				toast({
					msg:'保存到相册成功'
				})
				this.$refs.popup.close()
			},
			fail:(err)=>{
				console.log("保存到相册失败",err)
			}
		});
  //#endif 
}
}


</script>

总结:

涉及的知识点:

获取带对应参数的二维码,这个需要前后端商议如何对接

uniapp的canvas

uni.canvasToTempFilePath

uni.saveImageToPhotosAlbum

借鉴文章:https://www.jianshu.com/p/266545660eef

ThinkPHP5开发小程序推广分享参数二维码生成是一种在小程序中推广活动的有效方式。我们可以利用ThinkPHP5框架提供的接口和功能来实现这个需求。 首先,我们需要在小程序生成一个参数二维码。可以使用小程序提供的wx.getSceneParams方法来获取当前页面的参数,并将参数转化为字符串拼接到跳转链接中。然后,使用微信开放平台提供的qr_code接口生成一个参数二维码图片,并将图片保存到服务器上。 在ThinkPHP5中,我们可以创建一个二维码生成的控制器,接收前传来的参数,并根据参数生成二维码。可以使用EasyWeChat等第三方库来调用微信开放平台的接口生成二维码图片。生成二维码可以保存到服务器上的指定路径。 接下来,我们需要将生成二维码图片返回给前。在控制器中,可以使用ThinkPHP5提供的return方法将图片路径返回给前。前可以通过路径来展示二维码图片。 最后,我们可以在小程序中实现推广分享的逻辑。在用户点击分享按钮时,可以获取当前页面的路径和参数,并将路径和参数拼接到自定义分享链接中,生成一个参数分享链接。通过这个链接,其他用户进入小程序后,可以通过分享者的分享链接获得参数,从而参与相应的推广活动。 总结来说,使用ThinkPHP5开发小程序推广分享参数二维码生成,需要在小程序生成参数二维码图片,并利用ThinkPHP5提供的功能将图片保存到服务器上。然后,将生成二维码图片路径返回给前展示,并在小程序中实现推广分享的逻辑。这样,我们就可以实现小程序的推广分享功能,参数二维码生成和使用。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值