微信小程序通过canvas生成海报的问题总结

先交代一下背景,最近做一个微信小程序的项目,项目中有一个需求,就是生成日签和海报功能,最开始想通过微信小程序自带的canvas来实现,实际实现中,效果很不理想,通过drawImage写入到canvas中图片,不是显示不全,就是会出现很模糊的问题,总之距离想要达到的效果相距甚远,不断的查询资料中,找到了一个叫 wx-canvas-2d  的插件,基本上可以满足需求,接下来又遇到一个问题,需求是想生成一个1500*2400的海报,所以最开始是想,用两个canvas,一个用于显示给用户看,一个用生成下载,显示给用户看到背景图用的是300*480的背景图,下载用的背景图是1500*2400的,在电脑端是没有问题的,但是在wx.canvasToTempFilePath保存海报到手机默认相册时会失败,经测试发现,是因为生成的图片太大,导致保存失败,最后用显示给用户看那个canvas来生成海报保存,导出的尺寸可以设置成1500*2400,这样基本就满足需求了,下面上干货。

先上一下效果图。

1.第一步,使用 如何命令进行安装,当然前提是安装了npm的前提下,微信小程序中npm的安装以及需要注意的问题,会在另一篇文章详细介绍。

npm i -S wx-canvas-2d

2.安装成功后,在下面两个文件夹目录下面会有wx-canvas-2d的文件夹

3 安装成功后,到微信开发工具的工具选项里面点一下构建npm。

4.在wxml中写入canvas元素,本项目的需求在弹窗中显示海报,所以写了一个遮罩层,用了position:fixed;这个属性,但是有一个问题就是canvas在父级元素为position:fixed的情况下,会浮动出父级元素,跟随页面滑动,这显然不是想要的需求,最后只能不把canvas放到遮罩层里面,然后通过wxss来调整到想要显示的位置。

<!--遮罩层开始-->
<block  wx:if="{{posters}}" >


<view  id="shareshadwinfo" class="shareshadw"  catchtouchmove="noneEnoughPeople" >

<!--日签生成开始-->

<block  wx:if="{{posteritem}}" >

<view class="itemctn"  >

<!--图片范围开始-->

<view class="topimgctn" style="height:{{changeheightctn}};" >

<!--画布开始-->

<!--画布结束-->

<!--图片范围结束-->

   </view>  

<view class="bottomselect">  

<view class="itemsavctn" bindtap="saveshareimg" >

<view class="itemingctn"> <image class="img"  src="../../style/images/wxicon.png" > </image> </view>
<view class="itemword"   > 保存到相册</view>

</view>

<view class="itemsavctn itemsavctn-r"  bindtap="saveshareimg" >

<view class="itemingctn"> <image class="img"  src="../../style/images/wxicon.png"> </image> </view>
<view class="itemword"> 分享海报</view>

</view>

 </view>  

</view>
</block>
<!--日签生成结束-->

</view>

</block>

<!--遮罩层结束-->
<block  wx:if="{{posters}}" >
<view id="canvas-containershow"  class="canvas-containershow" style="height:{{changeheight}};" >
    <canvas
        type="2d"
        id="poster-canvasshow"
        class="poster-canvasshow"
        style="width: 100%; height: 100%;margin:0 auto;"
        disable-scroll="{{ true }}"
    />
</view > 

</block> 

5.然后就是写样式文件了,由于这里面的样式是根据我的项目需求所写的,不一定适用所有人,可能需要根据实际情况进行调整。

/*海报相关样式文件开始*/

.shareshadw{
 
 position:fixed;
  width:99%;
  left:0;
  right:0;
  top:0;
  bottom:0;
  z-index:99;

  background:rgba(0,0,0,0.55);
}

.itemctn{
  width:100%;
  height:100%;
}

.topimgctn{

  width:85%;
 /* height:72%;*/
  margin:0 auto;
  margin-top:80px;

}

.topimgctn .fooimg{
  width:100%;
  height:100%;
}

.bottomselect{
  display:flex;
  width:85%;
  height:40px;
  margin:10px auto;
}

.itemsavctn{
  display:flex;
  width:115px;
  height:40px;
  /*margin:0 10px;*/
  margin:auto;
  border-radius:50px;
  padding:0 10px;
  border:1px solid #eee;
}

.itemingctn{

  width:25px;
  height:25px;
  margin:8px 0;
}

.itemingctn .img{
  width:100%;
  height:100%;
}

.itemword{

  width:85px;
  height:40px;
  line-height:40px;
  text-align:left;
  color:#fff;
  margin:0 3px;
  font-size:15px;
}

.itemsavctn-r{

background:#07CF9F;
border:1px solid ##07CF9F;

}


.canvas-containershow{
position:relative;
  width:79%;
  margin:0 auto;
  margin-top:-1010px;
  z-index:999;
}

.canvas-container {

    margin-top:-100000px;
    width:1755rpx;
    height:2810rpx;
}

/*海报相关样式文件结束*/

6.在 js 文件中引入 wx-canvas-2d 插件,然后实例化 WxCanvas2d 对象,并创建画布

import WxCanvas2d from 'wx-canvas-2d' //引入wx-canvas-2d 

const canvasshow = new WxCanvas2d()  //实例化对象

//获取背景图 创建画布

savelocalimg:function(e){

var that=this;

const db = wx.cloud.database()

//获取日签海报图开始 
//此项目使用的是微信小程序的云开发系统,所以把海报的背景图放进了云开发的内容管理系统里面进行管理,需要先从后台获取背景图信息
db.collection('signaturebg').orderBy('_id', 'desc')
.get({
  success: function(res) {

if(res.data.length){

//这一块是控制根据需求显示和隐藏遮罩层的。
that.setData({

  sigimgurl:res.data[0].rqbgimg,
    qgcodeimgurl:res.data[0].qgcodeimg,
})


wx.showLoading({
  title: '日签生成中',
  duration: 1000,
}); 

//由于日签中需要用的当日的时间,所以通过util.js这个插件对要用到的时间进行处理。

var todayxq='';
var    todaybirtshxq=''
//const util = require('../../utils/util.js')
//获取设备宽度开始

var timestamp=new Date();
 var xqday=timestamp.getDay();

 if(xqday==1){

   todayxq='周一';
   todaybirtshxq='Monday'
}

if(xqday==2){

   todayxq='周二';
   todaybirtshxq='Tuesday'
}

if(xqday==3){

   todayxq='周三';
   todaybirtshxq='Wednesday'
}

if(xqday==4){

   todayxq='周四';
   todaybirtshxq='Thursday'
}

if(xqday==5){

   todayxq='周五';
   todaybirtshxq='Friday'
}

if(xqday==6){

   todayxq='周六';
   todaybirtshxq='Saturday'
} 

var todaytmboard=timestamp.getFullYear()+'年'+(timestamp.getMonth()+1)+'月'+timestamp.getDate()+'日  '+todayxq;

var leidkdaynum=that.data.ljdkdays;

that.setData({
  todaytmboardval:todaytmboard,
})

//console.log('海报时间'+todaytmboard)

//滚动轴滑到顶部开始

 wx.pageScrollTo({
        scrollTop: 0
      })   

//滚动轴滑到顶部结束

//这一块是根据不同的设备的动态调整画布的高度
 var showcanvasheight=0;
wx.getSystemInfo({
  success: function (res) {

    let clientHeight = res.windowHeight;
    let clientWidth = res.windowWidth;
    let changeHeight = 375 / clientWidth;
    let height = clientHeight * changeHeight;

  var shebeiwidth=res.windowWidth

var multiples=(clientWidth/320).toFixed(1);

 //  showcanvasheight=((clientWidth/320).toFixed(1)*408).toFixed(0);

showcanvasheight=((clientWidth/320).toFixed(1)*410).toFixed(0);

  var showcanvasheightval=showcanvasheight+'px';

   var showcanvasheightctnval=(parseInt(showcanvasheight)+(25*multiples))+'px';
  

   that.setData({
      changeheight: showcanvasheightval,
      changeheightctn: showcanvasheightctnval,
    });
}})



//获取设备宽度结束

 that.setData({
   posters:true,
posteritem:true,
 })

//海报显示开始

// 创建

canvasshow.create({
    query: '.poster-canvasshow', // 必传,canvasshow元素的查询条件
    rootWidth: 375, // 参考设备宽度 (即开发时UI设计稿的宽度,默认375,可改为750),这个参数用于可以控制图片背景在海报中显示的范围,比如如果背景图是1500*2400的,就需要把这个值调大一些,不然背景图会在画布中显示的不完整。
  //bgColor: '#ff0000',  // 背景色,默认透明
   bgColor: '#ffffff',  // 背景色,默认透明
    component: that, // 自定义组件内需要传 this  如果该方法不是在函数的最外层,就要用that,用this无法绘制成功。
   // radius: 16 // 海报图圆角,如果不需要可不填
}).then(res => {
    // console.log(res)

}).catch(err => {
    console.log('[Wxcanvasshow2d] canvasshow create fail: ', err)
})


// 绘制

canvasshow.draw({
    series: [

         {
            type: 'image', // 图片
            url: that.data.sigimgurl, //背景图地址
         //  url:'https://6a73-jsxzhj-9gn2l3gp6081732a-1305238372.tcb.qcloud.la/small.jpg?sign=e6f35655710038a889d5a9634efdf102&t=1617937394',
            x: 0,
            y: 0,
            width: 300, 
            height: 480,
            mode: 'aspectFill' // 图片的裁剪方式,参考小程序 image 标签的 mode 属性
            
        },

        {
            type: 'text',
            x:35,
            y:45,
            text: '一/起/暴/瘦',
            color:'#fff',
            fontSize: 25,
            lineHeight:'20',
        },

         {
            type: 'text',
            x:30,
            y:70,
            text: '自控力!  自律给我自由',
            color:'#fff',
            fontSize: 15,
            lineHeight:'42',
        }, 

         {
            type: 'text',
            x:90,
            y:132,
            text: '已经坚持打卡(天)',
            color:'#fff',
            fontSize: 18,
            lineHeight:'42',
        },   

        {
            type: 'text',
            x:110,
            y:240,
            text: leidkdaynum,
            color:'#fff',
            fontSize: 100,
            fontWeight:'bold',
            lineHeight:'42',
        },   

         {
            type: 'text',
            x:50,
            y:329,
            text: todaytmboard,
            color:'#fff',
            fontSize: 15,
            lineHeight:'30',
        },

        {
            type: 'text',
            x:30,
            y:359,
            text: 'You are',
            color:'#fff',
            fontSize: 12,
            lineHeight:'42',
        }, 

        {
            type: 'text',
            x:30,
            y:389,
            text: 'Backlit with all the good',
            color:'#fff',
            fontSize: 12,
            lineHeight:'30',
        },  

             {
            type: 'text',
            x:30,
            y:409,
            text: 'things in this good',
            color:'#fff',
            fontSize: 12,
            lineHeight:'30',
        }, 

         {
            type: 'text',
            x:200,
            y:415,
            text: '长按识别',
            color:'#fff',
            fontSize: 13,
            lineHeight:'25',
        },  
    {
            type: 'image', // 图片
            url: that.data.qgcodeimgurl, 这个是小程序二维码地址
         //  url:'https://6a73-jsxzhj-9gn2l3gp6081732a-1305238372.tcb.qcloud.la/qrcode.jpg?sign=4bc6492414feba96d9bcd474616a9047&t=1617854068',
            x: 200,
            y: 360,
            width: 50,
            height: 50,
            mode: 'aspectFill' // 图片的裁剪方式,参考小程序 image 标签的 mode 属性
        },
        {
            type: 'text',
            x:180,
            y:435,
            text: '一起享 "瘦" 生活',
            color:'#fff',
            fontSize: 13,
            lineHeight:'25',
        },                
        
    ]
}).then((res) => {
    console.log('绘制成功!')
    console.log(res)

}).catch(err => {
    console.log('绘制失败!', err)
})


//海报显示结束

}

else{

console.log('无海报背景图数据')


}

 }

})

//获取日签海报背景图结束


},

//保存生成的海报到手机默认相册。

saveshareimg:function(){

var that=this;

//console.log('保存图片')

//获取相册授权后开始执行结束

wx.getSetting({
  success(res) {

    
    if (!res.authSetting['scope.writePhotosAlbum']) {

      wx.authorize({
        scope: 'scope.writePhotosAlbum',
        success () {
        //  conosle.log('用户授权相册功能')
          // 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
         // wx.startRecord()
        }
      })
    }
    else{

//测试待删除开始    

wx.canvasToTempFilePath({  //使用这个方法,如果在微信开发工具里面能正常调用,在手机端就不行,可能是生成的海报过大的问题,一般不要超过2MB吧,该方法的目的只要获取海报的临时地址提供给wx.saveImageToPhotosAlbum调用,这个方法只接受本地绝对路径和临时地址,不接受网络地址或其他地址

canvas:canvasshow.canvas,  //这里需要注意的是,可以传canvasid,但是如果canvas里面有了type=2d这个参数,在传canvasid就不起作用了,但是这个插件又是用到type=2d这个属性写的,无法去掉,所以只能穿canvas对象,wx-canvas-2d这个插件的cnavas对象在实例canvasshow的canvas里面方法,不是实例后的对象canvasshow,这点需要注意,第一次使用可能会遇到这个问题。

destWidth:1500, //输出的海报高度
destHeight:2400, //输出的海报宽度,
success: (res) => {

console.log(res)

//执行保存图片到本地开始
wx.saveImageToPhotosAlbum({
 // filePath: res.tempFilePath,
//    filePath: '/style/picture/gif1.jpg',
//    filePath: '/style/picture/23.png',
    filePath: res.tempFilePath,
  success(res) { 

//console.log('保存图片到相册res值');
//console.log(res)

 that.setData({
   posters:false,
posteritem:false,
 })

  },
  fail:function(err){
  
console.log('保存失败')
console.log(err)
wx.showToast({
              title: "您取消了保存图片",
              duration: 2000
            })

 that.setData({
   posters:false,
posteritem:false,
 })


  }

})  

//执行保存图片到本地结束  


},

fail:function(err){

//console.log('获取图片临时路径失败')

console.log(err)

}

}) 


    }
  },
  fail(err){

    console.log('失败')
    console.log(err);
  }
})  

//获取相册授权后开始执行结束

// 保存图片到相册


},




7,虽然实现了,但是依然有一个小问题没解决,就是背景图不能在所有设备上都完全铺满画布,所以在某些设备上导出的海报底部可能会有白色背景。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值