在微信小程序中生成一张分享海报?

Posted 凉介,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在微信小程序中生成一张分享海报?相关的知识,希望对你有一定的参考价值。

前言

因产品需求,需要在小程序中生成一张分享海报用于产品推广。特此记录一波产出过程~

这次开发使用的是  uni-app 来产出小程序

 

Part.1  大致思路

按照设计图将所需元素全部画入 Canvas 画布,再利用 wx.canvasToTempFilePath(Object object, Object this)  API 将 Canvas 生成一张指定大小的图片,保存分享即可~

此API具体用法和注意事项可去 https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html 查看

 

Part.2  遇到的问题

1. 由于此次 Canvas 中的内容不是固定的,可能会有很多内容。所以第一个遇到的问题就是: Canvas 中的文字换行

2. 文字换行成功后又遇到一个新问题:需要换行的文字中 不能包含空格字符,否则内容排版会错乱

3. 由于可能出现内容很多,不可控的情况,所以 Canvas 的高度也不好确定 :  Canvas 高度不确定

4. 使用网络图片画入 Canvas 中

5. 产出的 Canvas  图片模糊不清

 

Part.3  解决问题

问题一: 解决 Canvas  文字换行的方法

技术图片
// canvas  文本换行绘制
        drawtext(ctx, t, x, y, w, num) {
            //参数说明
                //ctx:canvas的 2d 对象,t:绘制的文字,x,y:文字坐标,w:文字最大宽度
                let chr = t.split("");
                let temp = "";
                let row = [];
            
                for (let a = 0; a<chr.length;a++) {
                    if(ctx.measureText(temp).width < w && ctx.measureText(temp+(chr[a])).width <= w){
                        temp += chr[a];
                    }else{
                        row.push(temp);
                        temp = chr[a];
                    }
                };
                
                row.push(temp);
                let rowLength = row.length;
                
                if (num == 1) {
                    this.titleLineH = (rowLength + 1) * uni.upx2px(48); 
                } else {
                    this.contentLineH = (rowLength + 1) * uni.upx2px(48);
                };
                
            
                for (let b = 0; b < rowLength; b++){
                    ctx.fillText(row[b], x, y + (b + 1) * uni.upx2px(48));//每行字体y坐标间隔24
                }
        },
View Code

问题二:利用 xxx.replace(/s/g, ""),去掉内容中的空格字符

问题三: Canvas 高度设置为动态, 例:height: 5000px

问题四: 使用网络图片画入时,需先使用  uni.getImageInfo 这个API加载图片完成拿到临时地址后再绘入  Canvas ,否则很容易造成 Canvas 出现空白

问题五: 产出的 Canvas  图片模糊,只需将输出值扩大原来的两倍即可 ,如:200px 输出就为 400px

 

Part.4  代码展示

html

技术图片
 1 <template>
 2     <view class="layout-bg">
 3         
 4         <view class="scroll-Y">    
 5 
 6             <canvas canvas-id=‘share‘  
 7                     class="canvas-style"
 8                     :style="{height: canvasHeight + ‘px‘}"></canvas>     
 9         
10              <view class="img-box"> 
11                   <image class="img-placard"
12                          :style="{height: canvasHeight + ‘px‘}"
13                          @load="placardLoad()"
14                          :src="src"></image>
15               </view>
16               
17               <view :style="{height: canvasHeight + 100 + ‘px‘}"></view>
18          </view>
19          
20          
21          <view class="footer-btn">
22              <view class="row footer-left-box" hover-class="hover-active" @click="downloadWay()">
23                  <image class="btn-img preserve-ico"
24                        src="../../static/image/download-ico.svg"></image>
25                 <button class="btn-text  preserve-btn" 
26                        :class="text == ‘长按上方图片即可保存‘? ‘text-color‘ : ‘‘">{{text}}</button>
27              </view>
28              
29              <view class="btn-share-box row" hover-class="hover-active">
30                  <image class="btn-img share-ico" 
31                        src="../../static/image/share-ico.svg"></image>
32                 <button class="btn-text share-btn" open-type="share">分享</button>
33              </view>
34          </view>      
35     </view>
36 </template>
View Code

 

JS

技术图片
<script>

export default {
    data() {
        return {
            src: ‘‘,
            obj: {},
            content: ‘‘,
        
            simpleMsgTitle: 标题,
            simpleMsgTime: 2019-11-23 17:20,
            
            textTitle: 中振区块链技术全球战略合作媒体,
            textDesc: 扫码查询获取更多资讯,
            
            text: ‘‘,
            
            canvasHeight: 5000, // canvas 默认高度        
            
            canvasStatus: false,
            
            query: {}
        }
    },
    onLoad(event) {
        // #ifdef MP-WEIXIN
        uni.showLoading({
            title: 加载中
        });
        
        this.text = 下载分享海报
        // #endif
        
       try {
           this.obj = JSON.parse(decodeURIComponent(event.query));
       } catch (error) {
           this.obj = JSON.parse(event.query);
       };
       
       uni.setNavigationBarTitle({
           title: "快讯"
       });    
       
       this.query = this.obj;

        this.simpleMsgTitle = this.obj.title;
        this.simpleMsgTime = this.obj.datetime;
        this.content = this.obj.content;    
    },
    onReady() {        
         // 开始绘制海报
         this.setCanvas()
    },
    onShareAppMessage(res) {
        return {
            title: this.query.title,
            path: /pages/simpleMsg/share?query= + encodeURIComponent(JSON.stringify(this.query))
        }
    },
    methods: {
         // 开始绘制海报
        setCanvas() {
            // 判断图片是否加载完成
            let imgArr = [https://qdksm.zhongzhenbc.com/banner.png,
                          https://qdksm.zhongzhenbc.com/qdCode.png];

                uni.getImageInfo({
                    src: imgArr[0],
                    success: (img1)=> {
                        if (img1.path !== ‘‘) {
                            uni.getImageInfo({
                                src: imgArr[1],
                                success: (img2)=> {
                                    if (img2.path !== ‘‘) {
                                        const ctx = wx.createCanvasContext(share, this);
                                        ctx.fillStyle = "#2C3339";
                                        ctx.fillRect(0, 0, uni.upx2px(672), this.canvasHeight);
                                        ctx.drawImage(img1.path, 0, 0, uni.upx2px(672), uni.upx2px(202));  // h: 202
                                        ctx.setFontSize(uni.upx2px(24));
                                        ctx.setFillStyle(rgba(79,234,207,1));
                                        ctx.fillText(快讯, uni.upx2px(30), uni.upx2px(249));
                                        ctx.setFontSize(uni.upx2px(36));
                                        ctx.setFillStyle(rgba(255,255,255,1));
                                        ctx.fillText(奇点科商美, uni.upx2px(110), uni.upx2px(90));
                                        ctx.setFontSize(uni.upx2px(24));
                                        ctx.fillText(科技商业美学引领者, uni.upx2px(110), uni.upx2px(120));
                                        ctx.fillText(一站式前沿科技精英社区, uni.upx2px(110), uni.upx2px(150));
                                        ctx.setFontSize(uni.upx2px(32));
                                        this.drawtext(ctx, this.obj.title, uni.upx2px(30), uni.upx2px(259), uni.upx2px(612), 1)
                                        ctx.setFontSize(uni.upx2px(24));
                                        ctx.setFillStyle(rgba(105,117,130,1));
                                        ctx.fillText(this.obj.datetime, uni.upx2px(30), uni.upx2px(269) + this.titleLineH);
                                        ctx.setFontSize(uni.upx2px(28));
                                        ctx.setFillStyle(rgba(244,244,244,1));
                                        this.drawtext(ctx, "       "+this.obj.content.replace(/s/g, ""), uni.upx2px(30), uni.upx2px(279) + this.titleLineH, uni.upx2px(612), 2);
                                        ctx.moveTo (0, this.titleLineH + this.contentLineH + uni.upx2px(289));       //设置起点状态
                                        ctx.lineTo (uni.upx2px(672), this.titleLineH + this.contentLineH + uni.upx2px(289));       //设置末端状态
                                        ctx.drawImage(img2.path, uni.upx2px(30), this.titleLineH + this.contentLineH + uni.upx2px(315), uni.upx2px(160), uni.upx2px(160));
                                        ctx.setFontSize(uni.upx2px(24));
                                        ctx.setFillStyle(rgba(79,234,207,1));
                                        ctx.fillText(中振区块链技术全球战略合作媒体, uni.upx2px(272), this.titleLineH + this.contentLineH + uni.upx2px(362));
                                        ctx.setFillStyle(rgba(255,255,255,1));
                                        ctx.fillText(扫码查询获取更多资讯, uni.upx2px(392), this.titleLineH + this.contentLineH + uni.upx2px(412));
                                        
                                        this.canvasHeight = this.titleLineH + this.contentLineH + uni.upx2px(511); // 根据内容高度重新为 canvas 赋值高度
                                        
                                        ctx.lineWidth = 1;          //设置线宽状态
                                        ctx.strokeStyle = "#697582" ;  //设置线的颜色状态
                                        ctx.stroke();
                                        ctx.draw(true, ()=> {
                                            uni.canvasToTempFilePath({
                                              x: 0,
                                              y: 0,
                                              width: uni.upx2px(672),
                                              height: this.canvasHeight,
                                              destWidth: uni.upx2px(1244),
                                              destHeight: this.canvasHeight * 2,
                                              canvasId: share,
                                              success: (res)=> {
                                                  this.src = res.tempFilePath;
                                                  this.canvasStatus = true
                                              },fail(err) {
                                                  console.log(err)
                                              } 
                                            },this)
                                        },200); 
                                    }                
                                }
                            })    
                        }
                    }
                }) 
        },

        // canvas  文本换行绘制
        drawtext(ctx, t, x, y, w, num) {
            //参数说明
                //ctx:canvas的 2d 对象,t:绘制的文字,x,y:文字坐标,w:文字最大宽度
                let chr = t.split("");
                let temp = "";
                let row = [];
            
                for (let a = 0; a<chr.length;a++) {
                    if(ctx.measureText(temp).width < w && ctx.measureText(temp+(chr[a])).width <= w){
                        temp += chr[a];
                    }else{
                        row.push(temp);
                        temp = chr[a];
                    }
                };
                
                row.push(temp);
                let rowLength = row.length;
                
                if (num == 1) {
                    this.titleLineH = (rowLength + 1) * uni.upx2px(48); 
                } else {
                    this.contentLineH = (rowLength + 1) * uni.upx2px(48);
                };
                
            
                for (let b = 0; b < rowLength; b++){
                    ctx.fillText(row[b], x, y + (b + 1) * uni.upx2px(48));//每行字体y坐标间隔24
                }
        },
        
        // 海报加载完成事件
        placardLoad() {
            uni.hideLoading();
        },
        
        // 保存海报
        downloadWay() {
            let that = this;
            
            // #ifdef H5
             that.text = 长按上方图片即可保存;
            // #endif
            
            // #ifdef MP-WEIXIN
            that.text = 下载分享海报;
            
            uni.authorize({
                scope: scope.writePhotosAlbum,
                success() {
                   uni.saveImageToPhotosAlbum({
                       filePath: that.src,
                       success: function() {
                           uni.showModal({
                               title: 保存成功,
                               content: 已保存到相册,快去看看吧,
                               showCancel: false
                           })
                       }
                   })
                },fail:function() {
                    uni.showModal({
                      title: 提示,
                      content: 您点击了拒绝授权,将无法正常保存图片,点击确定可重新获取授权,
                      success: function (res) {
                        if (res.confirm) {
                          uni.openSetting({
                            success: (res) => {
                              if (res.authSetting["scope.writePhotosAlbum"]) {////如果用户重新同意了授权登录
                                uni.saveImageToPhotosAlbum({
                                    filePath: that.src,
                                    success: function() {
                                        uni.showModal({
                                            title: 保存成功,
                                            content: 已保存到相册,快去看看吧,
                                            showCancel: false
                                        })
                                    }
                                })
                              }
                            }, fail: function (res) {}
                          })
                        }
                      }
                    })                
                 }
            })
            // #endif
        }
    }
}
</script>
View Code

 

CSS

技术图片
<style scoped>

button::after{ 
    border: none
}
.scroll-Y {
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
}
 .canvas-style, .img-box {
     position: absolute;
     top: 40upx;
}
.canvas-style {
    width: 672upx;
    top: -9999rpx
}
.position-absolute {
    position: absolute;
}
.footer-btn, .row {
    flex-direction: row;
}    
.row {
    z-index: 9999;
}
.layout-bg {
    background-color: #20252B;
}

.footer-btn {
    width: 100%;
    height: 100upx;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: #2C3339;
    z-index: 9999;
}

.footer-left-box, .btn-share-box{
    width: 50%;
    height: 100upx;
    align-items: center;
    justify-content: center;
    border-radius: 10upx;
    position: relative;
}
.btn-img {
    width: 40upx;
    height: 40upx;
    position: absolute;
    top: 30upx
}
.preserve-ico {
    left: 89upx;
}
.share-ico {
    left: 138upx;
}
.btn-text {
    font-size: 24upx;
    font-weight:400;
    color:rgba(105,117,130,1);
    background-color: transparent;
}
.download-img {
    margin-left: 88upx;
}
.btn-download-box2 {
    width: 100%;
    justify-content: center;
}
.download-img2 {
    margin-left: 0upx;
}

.img-box,.img-placard {
    z-index: 998;
}
.share-btn,.preserve-btn {
    width: 100%;
    height: 100rpx;
    font-size: 24rpx;
    font-weight: 400;
    color: rgba(105,117,130,1);
    background-color: transparent;
    padding-left: 50upx;
    padding-right: 0;
    line-height: 104upx;
}
.hover-active {
    opacity: 0.9;
    background: #20252B;
}
.text-color {
    color:rgba(79,234,207,1);
}
.img-placard {
    width: 672upx;
    border-radius: 10upx;
    box-shadow: 0px 1px 3px rgba(34, 25, 25, 0.2);
}
button {
    padding-left: 0;
    padding-right: 60upx;
}
</style>
View Code

 

以上是关于在微信小程序中生成一张分享海报?的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序海报 uniapp

微信小程序海报 uniapp

微信小程序代码片段分享

微信小程序代码片段

微信小程序在微信上怎么显示?

微信小程序在微信上怎么显示?