小程序绘制海报的那些问题——记录一次uniapp小程序生成分享海报的问题及解决

最近做了一个需求,一个推广活动,在小程序中生成推广海报并且支持保存在手机相册,UI稿中呈现的是一个非全屏的固定宽高的海报图片,在保存的时候遇到了如下问题并一一解决

【问题1】开发者工具中可以正常绘制海报,真机上却不行

【解决】因为绘制的海报中包含banner和太阳码图片,需要使用内置方法.getImageInfo()获取解析一下图片信息,才能绘制在画布当中

【问题2】真机中偶现canvas画布中文字绘制不全

【解决】context.draw()这个行为是异步的,我们使用uni.canvasToTempFilePath的行为进行海报的绘制,使用settimeout处理异步即可

          context.draw(false, () => {
            setTimeout(() => {
              uni.canvasToTempFilePath({
                canvasId: "posterCanvas",
                destWidth: 558 * 2,
                destHeight: 770 * 2,
                success(res) {
                  _this.posterImgSrc = res.tempFilePath;
                }
              });
            }, 100);
          });

【问题3】生成的海报没有背景色,是透明的

【解决】之前使用的填充方式是context.setFillStyle("rgba(255, 255, 255, 255)");context.fillRect(0, 0, 279 * rpx, 385 * rpx);设置背景色,canvas生成海报之后导出,背景色始终为透明的,后来参考了网上的方案,设置context.fillStyle = "#fff";context.fillRect(0, 0, 279 * rpx, 385 * rpx);之后成功实现了带白色背景色导出,setFillStyle和直接设置属性有什么差别我一开始只是解决问题没有搞明白,后来多方查询,找到了原因如下:fillStyle 属性设置或返回用于填充绘画的颜色、渐变或模式。setFillStyle是用于设置填充色的方法,为什么在绘制海报的时候setFillStyle这个方法没有生效,在微信的官方api中终于找到了答案

CanvasContext.setFillStyle(string|CanvasGradient color)

从基础库 1.9.90 开始,本接口停止维护,请使用 CanvasContext.fillStyle 代替

设置填充色。

嗯,所以fillStyle生效了,哈哈哈

【问题4】多种移动端生成的海报显示有偏差,没有达到理想的效果

【解决】获取设备宽高,计算和标准设计稿的偏差,然后在绘制时,数值均用此偏差进行处理

//获取不同设备的宽高适配
let { windowWidth, windowHeight } = systemInfo;
let rpx = 1;
//个性化定义针对不同设备的单位比率,和标准设计稿375做比
rpx = windowWidth / 375;

【完整代码如下,绘制海报的方法!】生成海报(使用canvas绘制海报banner+中间提示文字+底部太阳码,简单的太阳码分享海报)的源码(注:我们的小程序是uniapp的开发的,所以wx. 均为uni.)

    drawCanvas() {
      //创建画布区域
      let context = uni.createCanvasContext("posterCanvas");
      //记录当前this
      let _this = this;
      //获取屏幕信息;
      let systemInfo = new Promise((res, rej) => {
        uni.getSystemInfo({
          success: data => {
            res(data);
          }
        });
      });
      systemInfo.then(systemInfo => {
        //获取不同设备的宽高适配
        let { windowWidth, windowHeight } = systemInfo;
        let rpx = 1;
        //个性化定义针对不同设备的单位比率,和标准设计稿375做比
        rpx = windowWidth / 375;
        //此处279和385为我的设计稿当中的海报宽高
        context.clearRect(0, 0, 279 * rpx, 385 * rpx);
        //设置海报背景为白色
        context.fillStyle = "#fff";
        //填充背景颜色
        context.fillRect(0, 0, 279 * rpx, 385 * rpx);
        let path = this.posterBanner;//我的posterbanner是一个固定的图片链接
        let imagePromise = [img1, img2];
        imagePromise = imagePromise.map(src => {
          return new Promise((res, rej) => {
            //不获取一下图片信息会导致图片在真机上绘制失败
            uni.getImageInfo({
              src,
              success: data => {
                console.log("imgdata--->", data);
                res(data);
              },
              fail(err) {
                console.log("err", err);
              }
            });
          });
        });
        Promise.all(imagePromise).then(imgsInfo => {
          context.drawImage(
            imgsInfo[0].path,
            12.5 * rpx,
            12.5 * rpx,
            254 * rpx,
            173 * rpx
          );
          context.setFontSize(14 * rpx);
          context.setTextAlign("center");
          context.setFillStyle("#390C59");
          context.fillText(
            "xxxxxxxxxxxx一段文字",
            (279 * rpx) / 2,
            205.5 * rpx
          );
          context.setFontSize(14 * rpx);
          context.setTextAlign("center");
          context.setFillStyle("#390C59");
          context.fillText("xxxx一段文字!", (279 * rpx) / 2, 226.5 * rpx);
          context.drawImage(
            imgsInfo[1].path,
            102 * rpx,
            262.5 * rpx,
            75 * rpx,
            75 * rpx
          );
          context.setFontSize(12 * rpx);
          context.setTextAlign("center");
          context.setFillStyle("#390C59");
          context.fillText("长按扫码查看详情", (279 * rpx) / 2, 360.5 * rpx);
          context.draw(false, () => {
            //因为draw是异步的,移动端偶发绘制文字丢失,所以增加settimeout
            setTimeout(() => {
              uni.canvasToTempFilePath({
                canvasId: "posterCanvas",
                destWidth: 558 * 2,
                destHeight: 770 * 2,
                success(res) {
                  //拿到生成的画布图片临时路径在res.tempFilePath中,可以自行存储或者赋值
                }
              });
            }, 100);
          });
        });
      });
    },

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值