1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 小程序生成分享海报 带小程序码 并保存图片

小程序生成分享海报 带小程序码 并保存图片

时间:2024-04-27 11:55:57

相关推荐

小程序生成分享海报 带小程序码 并保存图片

小程序生成分享海报,带小程序码

话不多说,先上效果图

效果图不是重点,海报基本都是大同小异,都是一些信息,加上一个小程序码,重点是如何将所有要素整合成跟效果图一样的图片。我们知道如果是H5的话,有html2canvas可以使用,非常方便,感兴趣的同志可以参考我的另一篇H5生成分享海报

但是,小程序没有提供类似的东西啊,怎么办呢,只能自己动手画了,这就用到了canvas了。

先上我自己项目里的代码吧,结合上图:

<!-- 画布canvas --><canvas style="width: 343px;height: {{canvasHeight+'px'}};position:fixed;top:-9999rpx;left:-9999rpx;z-index:999" canvas-id="mycanvas"/><!-- 分享海报弹出层 --><van-popup show="{{ true }}" position="center" safe-area-inset-top="{{true}}" overlay="{{false}}" bind:close="onClose" round><view class="share_bill" style="height:{{innerViewH}}"><view class="inner_view"><view class="top_name"><image src="{{activityDetail.activity_imgs[0]}}?x-oss-process=image/resize,m_fill,h_302,w_686"></image><view class="bg_view"></view><view class="title"><image src="{{memberDetail.headimgurl?(memberDetail.headimgurl+'?x-oss-process=image/resize,m_fill,h_96,w_96'):'../../images/avatar.png'}}"></image><text>{{nickname}}</text></view></view><view class="bottom_msg"><view class="msg_info"><view class="title"><text class="pub_tip">{{activityDetail.is_public==1?'公开':'非公开'}}</text>{{activityDetail.activity_name}}</view><view class="msg_list"><image class="msg_icon" src="../../images/hd_adress@2x.png"></image><text class="msg_text">{{activityDetail.wx_address}} | {{activityDetail.distance}}</text></view><view class="msg_list"><image class="msg_icon" src="../../images/hd_time@2x.png"></image><text class="msg_text">{{activityDetail.time}}</text></view><view class="msg_list"><image class="msg_icon" src="../../images/hd_enroll@2x.png"></image><text class="msg_text">总人数 {{activityDetail.can_sign_num}}</text><view class="fu_price"><text class="fu" wx:if="{{activityDetail.fee_type==1}}">¥</text><text class="price">{{activityDetail.fee_type==0?'免费':(activityDetail.fee_type==2?'AA收款':(activityDetail.man_fee>activityDetail.woman_fee?activityDetail.woman_fee:activityDetail.man_fee))}}</text></view></view></view><view class="logo_code"><view class="logo_box"><image src="../../images/share_logo.png"></image><view class="logo_msg"><text>羽乐papa报名</text><view>长按识别二维码参与</view></view></view><view class="code_box"><image src="{{codeImg}}"></image></view></view></view></view></view></van-popup>

waitCreate(){// 生成海报var that = thiswx.showLoading({title: '海报生成中···',mask:'true'})setTimeout(() => {var obj=wx.createSelectorQuery();obj.selectAll('.inner_view').boundingClientRect();obj.exec(function (rect) {that.setData({canvasHeight:rect[0][0].height})that.createNewImg()})}, 1500);},// 生成海报方法createNewImg: function () {var that = this;//绘制海报底板,宽343,高海报的高度that.data.canvasHeight,圆角8;具体尺寸可根据实际设计图自己修改var context = wx.createCanvasContext('mycanvas');context.arc(8, 8, 8, Math.PI, Math.PI*1.5)context.arc(343 - 8, 8, 8, Math.PI * 1.5, Math.PI * 2)context.arc(343-8, that.data.canvasHeight - 8, 8, 0, Math.PI * 0.5)context.arc(8, that.data.canvasHeight - 8, 8, Math.PI * 0.5, Math.PI)context.clip()context.strokeStyle = "#ffffff";context.fillStyle="#ffffff"context.fill()// context.stroke();context.drawImage(that.data.activityCanvasPath, 0, 0, 343, 151);//绘制活动图片context.save()// 绘制昵称蒙层const grd = context.createLinearGradient(0, 0, 0, 343)grd.addColorStop(0, 'rgba(0, 0, 0, 0)')grd.addColorStop(1, 'rgba(0, 0, 0, 0.3)')context.setFillStyle(grd)context.fillRect(0,103,343,48);// 绘制昵称context.setFontSize(15);context.setFillStyle('#ffffff');context.setTextAlign('left');context.fillText(utils.StringExchangeEmoji(that.data.memberDetail.nickname),60,113+15)context.restore()// 绘制公开非公开context.setFontSize(13);context.setFillStyle('#ffffff');context.setTextAlign('left');var pub_w = 0;if(that.data.activityDetail.is_public==1){pub_w = context.measureText('公开').width+8}else{pub_w = context.measureText('非公开').width+8}console.log(pub_w)context.save()context.beginPath();const pub_bg = context.createLinearGradient(0, 0, pub_w,0)pub_bg.addColorStop(0, 'rgba(0, 84, 220, 0.4)')pub_bg.addColorStop(1, 'rgba(0, 209, 162, 0.4)')context.arc(16+2, 170+2, 2, Math.PI, Math.PI*1.5)context.arc(16+pub_w - 2, 170+2, 2, Math.PI * 1.5, Math.PI * 2)context.arc(16+pub_w-2, 170+18 - 2, 2, 0, Math.PI * 0.5)context.arc(16+2, 170+18 - 2, 2, Math.PI * 0.5, Math.PI)context.setFillStyle(pub_bg)context.fill()context.closePath();context.restore()context.fillText(that.data.activityDetail.is_public==1?'公开':'非公开',20,170+13);// 绘制活动名称context.setFontSize(17);context.setFillStyle('#333333');context.setTextAlign('left');let s = "我是a_dddhuo互动名称11111111受到冲击难道就省的111吨吨吨吨"let str = that.data.activityDetail.activity_name.split("")var temp = '';var row = [];for(var i = 0;i<str.length;i++){console.log(row,'row???')console.log(context.measureText(temp),'measureTextwidth???')if(row.length<1){if(that.data.activityDetail.is_public==1){if(context.measureText(temp).width < 269){}else{row.push(temp);temp = "";}}else{if(context.measureText(temp).width < 256){}else{row.push(temp);temp = "";}}}else{if(context.measureText(temp).width < 311){}else{row.push(temp);temp = "";}}temp += str[i];}row.push(temp)console.log(row,'row')for(var b = 0; b < row.length; b++){if(b==0){context.fillText(row[b],that.data.activityDetail.is_public==1?58:71,167+(b+1)*17);context.fillText(row[b],that.data.activityDetail.is_public==1?(58+0.5):(71+0.5),167+(b+1)*17+0.5);}else{context.fillText(row[b],16,167+(b+1)*17);context.fillText(row[b],16+0.5,167+(b+1)*17+0.5);}}context.save()// 绘制地址人数时间信息context.drawImage('/images/hd_adress@2x.png', 16, 201+row.length*17-17, 14, 14);context.setFontSize(13);context.setFillStyle('#999999');context.setTextAlign('left');let name_str = that.data.activityDetail.wx_address.split("")var name_temp = '';var name_row = [];for(var i = 0;i<name_str.length;i++){if(context.measureText(name_temp).width < 277){}else{name_row.push(name_temp);name_temp = "";}name_temp += name_str[i];}name_row.push(name_temp)for(var b = 0; b < name_row.length; b++){context.fillText(name_row[b], 34, 199+(b+1)*13+row.length*17-17);}context.drawImage('/images/hd_time@2x.png', 16, 223+(name_row.length*13)-13+row.length*17-17, 14, 14);context.fillText(that.data.activityDetail.time, 34, 221+(name_row.length*13)+row.length*17-17);context.drawImage('/images/hd_enroll@2x.png', 16, 245+(name_row.length*13)-13+row.length*17-17, 14, 14);context.fillText('总人数'+that.data.activityDetail.can_sign_num, 34, 243+(name_row.length*13)+row.length*17-17);// 价格context.restore()context.setFontSize(15);context.setFillStyle('#F13138');context.setTextAlign('left');if(that.data.activityDetail.fee_type==0){let w = context.measureText('免费').widthcontext.fillText('免费', 343-16-w, 237+15+(name_row.length*13)-10+row.length*17-17);}if(that.data.activityDetail.fee_type==2){let w = context.measureText('AA收款').widthcontext.fillText('AA收款', 343-16-w, 237+15+(name_row.length*13)-10+row.length*17-17);}if(that.data.activityDetail.fee_type==1){if(that.data.activityDetail.man_fee>that.data.activityDetail.woman_fee){let w = context.measureText('¥'+that.data.activityDetail.woman_fee).widthcontext.fillText('¥'+that.data.activityDetail.woman_fee, 343-16-w, 237+15+(name_row.length*13)-10+row.length*17-17);}else{let w = context.measureText('¥'+that.data.activityDetail.man_fee).widthcontext.fillText('¥'+that.data.activityDetail.man_fee, 343-16-w, 237+15+(name_row.length*13)-10+row.length*17-17);}}// context.fillText('¥'+that.data.activityDetail.man_fee, 297, 278+13+row.length*17-17);// 画线context.save()context.moveTo(16,277+(name_row.length*13)-13+row.length*17-17)context.lineTo(327,277+(name_row.length*13)-13+row.length*17-17)context.strokeStyle="#E5E5E5"context.stroke()// 绘制logocontext.restore()context.drawImage('/images/share_logo.png', 16, 319+(name_row.length*13)-13+row.length*17-17-30, 48, 48);// 绘制小程序码context.drawImage(that.data.codeCanvasPath, 227, 293+(name_row.length*13)-13+row.length*17-17-15, 100, 100);context.setFontSize(15);context.setFillStyle('#333333');context.setTextAlign('left');context.fillText("羽乐papa报名", 76, 319+15+(name_row.length*13)-13+row.length*17-17-30);context.setFontSize(13);context.setFillStyle('#999999');context.setTextAlign('left');context.fillText("长按识别二维码参与", 76, 346+19+(name_row.length*13)-13+row.length*17-17-30);context.save()// 画头像context.beginPath();context.arc(32, 123, 16, 0, 2 * Math.PI) //画出圆context.strokeStyle = "#ffffff";context.fill()context.clip(); //裁剪上面的圆形context.drawImage(that.data.avatarCanvasPath, 16, 107, 32, 32); // 在刚刚裁剪的园上画图context.restore();context.closePath();context.draw();setTimeout(function () {wx.hideLoading()wx.canvasToTempFilePath({//画出的海报转成图片链接,页面展示用,或保存图片时用canvasId: 'mycanvas',success: function (res) {var tempFilePath = res.tempFilePath;console.log("海报的图片链接",tempFilePath)that.setData({imagePath:tempFilePath})},fail: function (res) {console.log(res);}});}, 1000);},

逐步解析:

1,首先是画海报的整个底板,也就是接下来的画板区域,它决定了你的有效绘画区域,就跟你拿张纸画画一样,你能画的地方就只限于这张纸上。context.arc(x,y,r,sAngle,eAngle,counterclockwise) 方法创建弧/曲线(用于创建圆或部分圆)。x,y圆心坐标,r圆半径,sAngle起始角,eAngle结束角,counterclockwise,可选,false顺时针,true逆时针。

2,context.clip(),剪切;

3,context.strokeStyle,笔触颜色,就是啥颜色的笔画;

4,context.fillStyle,填充色,可以理解为背景颜色;

5,context.fill(),填充当前的图像(路径);

6,context.drawImage(img,x,y,width,height),将现有图片绘制到canvas上,img图片地址,x,y坐标,width,height宽高大小;

7,context.save(),把当前状态的一份拷贝压入到一个保存图像状态的栈中。这就允许您临时地改变图像状态,然后,通过调用 restore() 来恢复以前的值。与context.restore()成对出现;

8,context.createLinearGradient(x0,y0,x1,y1),创建线性的渐变对象。渐变可用于填充矩形、圆形、线条、文本等等。x0渐变开始点的 x 坐标,y0渐变开始点的 y 坐标,x1渐变结束点的 x 坐标,y1渐变结束点的 y 坐标;

9,grd.addColorStop(),渐变对象中的颜色和位置;

10,context.setFillStyle,设置或返回用于填充绘画的颜色、渐变或模式;

11.context.fillRect(x,y,width,height),绘制"已填充"的矩形,x,y矩形左上角的坐标;

12,context.setFontSize(),设置字体大小;

13,context.setTextAlign(),设置字体对齐方式;

14,context.fillText(text,x,y,maxWidth),在画布上绘制填色的文本,text要绘制的文字,x,y起始坐标,相对于画布,maxWidth可选,允许的最大文本宽度,以像素计;

15,context.measureText(text).width,返回字体的宽度,text要测量的字体,可用于判断字体太多,进行换行绘制;

16,context.beginPath(),开始一条路径,或重置当前的路径;

17,context.closePath(),创建从当前点到开始点的路径;

18,context.moveTo(x,y),把路径移动到画布中的指定点,不创建线条,路径目标位置坐标;

19,context.clip(),从原始画布中剪切任意形状和尺寸,一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。您也可以在使用 clip() 方法前通过使用 save() 方法对当前画布区域进行保存,并在以后的任意时间对其进行恢复(通过 restore() 方法);

20,context.draw(),整体绘制。

绘制完成后,wx.canvasToTempFilePath(),微信小程序的这个方法,可以生成canvas图片链接。接下来就是保存图片,同样微信小程序也提供了对应的方法,

// 点击保存图片saveImg(){var that = this// console.log(mycanvas,'mycanvas')// 保存图片wx.canvasToTempFilePath({canvasId: 'mycanvas',success: function (res) {var tempFilePath = res.tempFilePath;console.log("海报的链接",tempFilePath)that.setData({imagePath:tempFilePath})wx.saveFile({tempFilePath: tempFilePath,success (res) {console.log("resresrese",res)const savedFilePath = res.savedFilePathwx.saveImageToPhotosAlbum({filePath: savedFilePath,success: function (res) {wx.showToast({title: '已保存至手机相册',icon:'none',duration:2000})},fail: function (res) {wx.showToast({title: '请在左上角设置中开启保存相册权限!',icon:'none',duration:5000})},})}})},fail: function (res) {console.log(res);}});},

备注:值得一提的是,小程序在context.drawImage()绘制图片的时候,是不支持网络路径的图片的,支、只支持本地路径的图片!!!!解决办法,将线上路径的图片转化为本地路径的图片:

this.setImgPath(res.data.param.url).then(function(data){that.setData({codeCanvasPath:data})})// 链接图片转画图路径setImgPath(path){//传入图片线上路径return new Promise((resolve,reject)=>{wx.getImageInfo({src:path,success (res) {resolve(res.path)}});})},

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。