前端生成分享海报兼容H5和小程序

  • A+
所属分类:Web前端
摘要

### 移动端分享海报生成最近做项目需求是生成商品分享海报,并且保存到手机中要兼容H5和小程序<br>

### 移动端分享海报生成

最近做项目需求是生成商品分享海报,并且保存到手机中要兼容H5和小程序<br>

与后端同学沟通后,海报在前端生成最省性能和有较好的交互体验,先看做好的效果

 

前端生成分享海报兼容H5和小程序前端生成分享海报兼容H5和小程序​          前端生成分享海报兼容H5和小程序前端生成分享海报兼容H5和小程序

前端框架使用的是uni-app方便打包成H5和小程序

实现方案是拿到后端返回的数据后,利用canvas画布把各个数据拼在一起并且生成一张图片

主要的参数有:背景图、商品图、二维码、价格、原价、标题

 

首先拿到产品图和二维码之后需要把它们下载下来用uni-app的api就可以

先写一个下载方法并且在 template 定义画布组件

<template>  <canvas class="canvas" canvas-id="myCanvas" v-if="canvasStatus"></canvas>  </template>  onReady(){    this.downloadFileImg('','pic');    this.downloadFileImg('','code');  },  methods:{    downloadFileImg(url,name){      let self = this      uni.downloadFile({        url: url,        success: function(res) {          self[name] = res.tempFilePath;        },        fail: function(erros) {          console.log(error)        }      });    }  }

前端生成分享海报兼容H5和小程序

这样图片就暂时保存到本地临时文件了

 uni.downloadFile  需要注意的是

在各个小程序平台运行时,网络相关的 API 在使用前需要配置域名白名单。在h5上是跨域的,用户需要处理好跨域问题。

下来编写canvas生成图片的方法

/**      * 获取分享海报      * @param array imgArr 海报素材 0 背景图 1商品图 2二维码      * @param string store_name 素材文字      * @param string price 价格      * @param string ot_price 原始价格      * @param function successFn 回调函数  */  PosterCanvas: function(imgArr, store_name, price, ot_price, successFn) {      let that = this;      uni.showLoading({          title: '海报生成中',          mask: true      });      const ctx = uni.createCanvasContext('myCanvas');      ctx.clearRect(0, 0, 0, 0);        /**      * 只能获取合法域名下的图片信息,本地调试无法获取      *       */      ctx.fillStyle = '#fff';      ctx.fillRect(0, 0, 750, 1150);      uni.getImageInfo({          src: imgArr[0],          success: function(res) {              const WIDTH = res.width;              const HEIGHT = res.height;              ctx.drawImage(imgArr[1], 0, 0, WIDTH, WIDTH);              ctx.save();              let r = 110;              let d = r * 2;              let cx = 480;              let cy = 790;              ctx.arc(cx + r, cy + r, r, 0, 2 * Math.PI);              // ctx.clip();              ctx.drawImage(imgArr[2], cx, cy, d, d);              ctx.restore();              const CONTENT_ROW_LENGTH = 20;              let [contentLeng, contentArray, contentRows] = that.textByteLength(store_name, CONTENT_ROW_LENGTH);              if (contentRows > 2) {                  contentRows = 2;                  let textArray = contentArray.slice(0, 2);                  textArray[textArray.length - 1] += '……';                  contentArray = textArray;              }              ctx.setTextAlign('left');              ctx.setFontSize(36);              ctx.setFillStyle('#000');              // let contentHh = 36 * 1.5;              let contentHh = 36;              for (let m = 0; m < contentArray.length; m++) {                  if (m) {                      ctx.fillText(contentArray[m], 50, 1000 + contentHh * m + 18, 1100);                  } else {                      ctx.fillText(contentArray[m], 50, 1000 + contentHh * m, 1100);                  }              }              ctx.setTextAlign('left')              ctx.setFontSize(72);              ctx.setFillStyle('#DA4F2A');              ctx.fillText('¥' + price, 40, 820 + contentHh);                ctx.setTextAlign('left')              ctx.setFontSize(36);              ctx.setFillStyle('#999');              ctx.fillText('¥' + ot_price, 50, 876 + contentHh);              var underline = function(ctx, text, x, y, size, color, thickness, offset) {                  var width = ctx.measureText(text).width;                  switch (ctx.textAlign) {                      case "center":                          x -= (width / 2);                          break;                      case "right":                          x -= width;                          break;                  }                    y += size + offset;                  ctx.beginPath();                  ctx.strokeStyle = color;                  ctx.lineWidth = thickness;                  ctx.moveTo(x, y);                  ctx.lineTo(x + width, y);                  ctx.stroke();              }              underline(ctx, '¥' + ot_price, 55, 865, 36, '#999', 2, 0)              ctx.setTextAlign('left')              ctx.setFontSize(28);              ctx.setFillStyle('#999');              ctx.fillText('长按或扫描查看', 490, 1030 + contentHh);              ctx.draw(true, function() {                  uni.canvasToTempFilePath({                      canvasId: 'myCanvas',                      fileType: 'png',                      destWidth: WIDTH,                      destHeight: HEIGHT,                      success: function(res) {                          uni.hideLoading();                          successFn && successFn(res.tempFilePath);                      }                  })              });          },          fail: function(err) {              uni.hideLoading();              that.Tips({                  title: '无法获取图片信息'              });          }      })  },

前端生成分享海报兼容H5和小程序

首先创建一个canvas 画布

获取背景图图片信息拿到宽和高再绘制商品图片并保存

接下来绘制二维码并把坐标放好并保存

在处理文字换行问题并设置大小颜色和对其方式

在相对应的设置价格和原价的颜色和大小还有坐标

由于价格还有条横线,我在网上又搜下了横线的做法直接看方法就行

最后生成图片信息并且使用uni.canvasToTempFilePath 方法把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径。

这样我们就得到一个.png的临时文件现在就剩最后一步把文件渲染到组件里了,从回调函数就可以回去到

此方法用的比方比较多我把它写到公共方法里面并且绑定到vue原型上面方便我们后面使用

现在编写方法调用

handelCanvas(){      let imgArr = ['背景图路径',this.pic,this.code]      this.$util.PosterCanvas(imgArr,'标题','价格','原价',function(tempFilePath){          console.log(tempFilePath)      })  }

前端生成分享海报兼容H5和小程序

这样就拿到生成好的图片的是一个临时文件 现在把他放到页面中展示就ok了

保存图片功能H5可以长按保存图片这里只用处理小程序的就行

首先检测授权拿到授权后调用uni-app的api就可以了

savePosterPath: function() {      let that = this;      uni.getSetting({          success(res) {              if (!res.authSetting['scope.writePhotosAlbum']) {                  uni.authorize({                      scope: 'scope.writePhotosAlbum',                      success() {                          uni.saveImageToPhotosAlbum({                              filePath: 'canvas生成的临时图片',                              success: function(res) {                                  ....成功了                              },                              fail: function(res) {                                  ....失败了                              }                          });                      }                  });              } else {                  uni.saveImageToPhotosAlbum({                      filePath: 'canvas生成的临时图片',                      success: function(res) {                          ....成功了                      },                      fail: function(res) {                          ....失败了                      }                  });              }          }      });  },

前端生成分享海报兼容H5和小程序

这样前端生成海报就大功告成了,你学废了吗?

最后打一波广告:

CRMEB商城一个免费开源项目

移动端使用uni-app框架目前已经适配