小程序分享模块超级详解(推荐)


Posted in Javascript onApril 10, 2019

导语:在小程序项目开发中,分享能力几乎是每个项目必备的要求,但原生的分享能力比较有限,不够灵活,今天就我们就一起来研究下,如何在现有基础上,增强小程序分享的能力,使信息传递更加直观、灵活。

示例项目地址: https://github.com/ycvcb123/share-system

小程序分享基础 API 介绍

微信分享的 API 只提供了分享给微信好友的能力,并没有提供分享朋友圈的能力,这是为啥子呢!!!

从网上收集的一些咨询来看,主要有如下两点原因:

  1. 由于微商泛滥,公众号鸡汤泛滥,朋友圈质量已经有所下降,如果小程序再开放分享朋友圈功能,可能会进一步影响到整个微信生态,造成用户活跃度下降,用户流失等问题。
  2. 微信不让小程序在朋友圈转发,更多是保护朋友圈的”广告位”阵地,不能够让这块”肥肉”变成了公益设施。

其实一些童鞋应该留意到了在朋友圈,官方已经推了一些小程序的广告,只不过这项能力还没有完全放开,以后会不会放开先不讨论,智慧的开发小哥哥早已想到了通过生成带有小程序码的海报作为替代方案(撒花!!!),本文后面的部分也会说到,我们先回到正题。

onShareAppMessage -- 转发

用法:

Page({
  onShareAppMessage: function(){
     return {
      title: 'xxxxx', //自定义转发标题
      path: '/page/user?id=123', //分享页面路径
      imageUrl: '/common/images/xxx.png' //分享图片 宽高比 5:4
    }
  }
})
//如果只写成如下形式,title默认是小程序名,path为当前页面路径(不带参数),imageUrl为当前页面截图
Page({
  onShareAppMessage: function(){}
})

触发方法(一定要在 page 中先写入上述方法):

  1. 点击小程序的胶囊菜单,会从底部弹出转发选项。
  2. <button> 组件 open-type="share" 即 <button open-type="share"> ,点击后触发。

触发后效果如下:

小程序分享模块超级详解(推荐)

观察上述结果,不难看出, title 能分享出去的信息非常有限,那我们能不能对分享的图片做些文章,让它带出更多的信息呢?下面进入到我们的第二个部分基于 canvas 动态绘制分享图片

基于 canvas 动态绘制分享图片

因为每个页面的信息很多都是通过接口返回或者用户输入产生,是在不断变化的,设计师所画的静态图片肯定是不足以去展示这些信息的,那么我们就要想,有没有一种办法,是可以把 静态图片动态信息 绘制在一起后在生成一张 新的图片 ?答案是肯定的!!!

把图片和文字画在一起?我们就一定会想到神奇的 canvas ,根据小程序 画布 相关的 API 绘制如下:

//创建画布(组件中一定要绑定this,切记!!!)
var ctx = wx.createCanvasContext('myCanvas', this);
//画布上绘制图片
ctx.drawImage(path, 0, 0, width, height);
//画布上绘制文字
ctx.setFillStyle('#fff');
ctx.setFontSize(32);
ctx.fillText(startTime, 24, 54);
//其他信息绘制
//... 
ctx.draw();

上述已经通过 canvas 把图片和文字绘制到了一起,那如何把这个画布转成一个图片,供开发者使用呢?

强大的小程序给我们提供了原生的方法: wx.canvasToTempFilePath

//在上面代码的draw()的回调中使用wx.canvasToTempFilePath
var that = this;
ctx.draw(true, () => {
  setTimeout(() => {
    wx.canvasToTempFilePath({
      canvasId: 'myCanvas',
      success: (res) => { 
        that.setData({
          //res.tempFilePath 生成图片的临时路径
          picUrl: res.tempFilePath
        });
        
        
      }
    }, that); //在组件中使用这里一定记得要绑定this,切记!!!
  }, 300); //此处加入300毫秒延时是为了解决小程序绘制过程中的渲染问题
});

把图片路径传递给 <image> 标签,得到下图结果。

<image src="{{picUrl}}"/>

小程序分享模块超级详解(推荐)

同理:把 picUrl 赋值给 onShareAppMessage 中的 imageUrl ,分享出去后的图片则带有了动态信息!

对不同来源图片的处理(本地图片, 网络图片 , base64图片 )

在上面的例子中,绘制本地图片时直接使用 ctx.drawImage(path, 0, 0, width, height) , path 直接传入图片路径即可。但是如果是 网络图片 或者是 base64 的图片时, drawImage 是无法直接绘制的 ,下面就介绍下针对上述两种情况如何做兼容处理。

网络来源图片

//将网络图片转换为本地路径
handleNetImg: function(imagePath) {
  var that = this;
  return new Promise((resolve, reject) => {
    wx.getImageInfo({
      src: imagePath,
      success: function(res) {
        resolve(res);
      }
    });
  });
}

handleNetImg('网络图片地址').then((res) => {
  console.log(res.path); //输出转换后的本地图片路径
  ctx.drawImage(res.path, 0, 0, width, height); //此时图片即可在画布上绘制出来
})

base64 图片

使用 ctx.drawImage(base64Data, 0, 0, width, height) 在小程序开发者工具上是可以绘制的, 然而!!!这个大骗纸!!!真机上是失效的!!!(心碎一分钟。。。)

跟上面类似的思路,我们把 base64的图片 转为本地的 png图片

var handleBase64Img = function() {
  //wx.getFileSystemManager 小程序文件管理器
  var fsm = wx.getFileSystemManager();
  var FILE_NAME = 'base64src';
  var base64src = function(base64data) {
    return new Promise((resolve, reject) => {
      //解析base64,提取出图片类型: imgtype,解析内容bodyData(去掉data:image/png;base64,以后的内容)
      var [, imgType, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || [];
      if (!imgType) {
        reject(new Error('ERROR_BASE64SRC_PARSE'));
      }
      /**
       *wx.env.USER_DATA_PATH
       *本地用户文件
       *本地用户文件是从 1.7.0 版本开始新增的概念。提供了一个用户文件目录给开发者,开发者对这个目录有完全自由的读写权限。通过 wx.env.USER_DATA_PATH 可以获取到这个目录的路径。
       */
      var filePath = `${wx.env.USER_DATA_PATH}/${FILE_NAME}.${imgType}`;
      //按指定写入文件的字符编码encoding,向地址filepath,写入数据data。
      fsm.writeFile({
        filePath,
        data: bodyData,
        encoding: 'base64',
        success() {
          resolve(filePath);
        },
        fail() {
          reject(new Error('ERROR_BASE64SRC_WRITE'));
        },
      });
    });
  };
  return base64src;
}

var base64src = that.handleBase64Img();
var handleBase64src = base64src(base64data);
handleBase64src.then(res => {
  //res 即为base64 转化为图片后的本地路径,即可在画布上绘制成功
  that.ctx.drawImage(res, left, top, width, height);
});

通过上述的一些内容,我们已经知道如何利用 canvas 把图片和文字绘制在一起后生成一张新的图片,这里就产生了一个新的问题: 我们如何把生成的图片保存下来呢 ??? 我们接着往细看canvas 生成图片后如何保存到本地

canvas 生成图片后如何保存到相册中

想要保存到相册中第一步首先当然是要获得访问相册的权限!!!

小程序分享模块超级详解(推荐)

//访问相册授权
wx.getSetting({
  success: (res) => {
    //检查是否有访问相册的权限,如果没有则通过wx.authorize方法授权(授权只需要一次就好,后面就可以直接访问相册)
    if (!res.authSetting['scope.writePhotosAlbum']) {
      console.log('没有获取授权');
      wx.authorize({
        scope: 'scope.writePhotosAlbum',
        success: (res) => {
          //用户点击允许获取相册信息后逻辑进入这里,如上图所示
        }
      })
    } 
  }
});

//获取了相册的访问权限,使用 wx.saveImageToPhotosAlbum 将图片保存到相册中
wx.saveImageToPhotosAlbum({
  filePath: that.data.sharePicPath,
  success: (res) => {
    //保存成功弹出提示,告知一下用户
    wx.showModal({
      title: '已保存到手机相册',
      content: '将图片发送到朋友圈,邀请好友加入',
      confirmColor: '#0bc183',
      confirmText: '知道了',
      showCancel: false
    })
  }
})

如何生成小程序码及验证小程序码所带信息

在小程序的分享朋友圈的解决方案中,往往在生成的海报页面中都会有一个小程序码,使得用户有进入小程序的入口,那么这个小程序码如何生成呢?

官方文档:获取小程序码

小程序分享模块超级详解(推荐)

注意:因为生成小程序码的接口参数需要 access_token,安全起见,一般都通过后台调用在拿到base64的数据在返回给前端。

我们在回到正题:

上述三种生成接口,大家根据情况按需使用,因为我的项目里,需要经常生成不同页面对应的小程序码, B 类接口比较符合我的要求,这里就重点描述下 B 类接口的 使用 和 自测

B 类接口入参,出参官方说明-- 接口 B:适用于需要的码数量极多的业务场景

重点看下 scene : 最大32个可见字符,有页面路径带参数的情况下要尤其注意!!!

小程序分享模块超级详解(推荐)

page , scene 等参数传递给后台后,后台调用 B 类接口,返回给前端一个base64的图片数据,我们把这个数据绘制到海报上就好!!!

绘制方法上面已经说过canvas 对不同来源图片的处理(本地图片, 网络图片 , base64图片 )

现在小程序码的图片已经生成了,那么我们要如何自测呢?怎么才能知道小程序码中所携带信息是否正确呢?

官方给出的方法:

小程序分享模块超级详解(推荐)

上述方法在开发阶段是比较方便,但是在正式的提测阶段,此种方式显得有些牵强,有人想到真机调试?

官方接口只能生成已发布的小程序的二维码

也就是说,你扫码就连上生产环境了!!!没有办法调试,那到底怎么办呢???

解决办法就要借助强大的小程序开发者工具啦!!!

首先把生成的小程序码保存到电脑里,方法见上述canvas 生成图片后如何保存到本地部分。

然后通过开发者工具选择二维码编译模式,文件夹中选择带有小程序码的图片即可!!!

小程序分享模块超级详解(推荐)

注意: 获取 scene 值时要 decodeURIComponent

Page({
 onLoad(query) {
  // scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene
  const scene = decodeURIComponent(query.scene)
 }
})

抽离配置文件,使绘制更加灵活

我们观察如下一个小程序海报:

小程序分享模块超级详解(推荐)

除了上图红框中的的内容会发生写变化以外,整体的结构大部分是基本已经固定了的,因为海报内容和业务是强相关的,如果我把绘制的逻辑写入组件里,那岂不是换个业务,我的组件就要改一次?这样失去了组件的通用型肯定是不行的,那怎么办呢?下面介绍一个业界比较好的解决方案:

小程序海报说白了就是由 canvas 画布上绘制的一些形状,图片,文字,线等等组成的,那我们是不是可以把这些绘制的基本能力封装成方法,通过设计稿量出海报上每个元素的位置大小等信息,当作一个配置文件传递给这些绘制方法,这样就保证组件的通用型,而且绘制信息抽离成一个配置文件也更加方便后期维护。

share-config.js:

function setShareInfo(time, start, end, imageSrc) {
  return {
    width: 750,
    height: 1300,
    background: '#F2FCF8',
    views: [{
        type: 'rect',
        parent: true,
        radius: true,
        radiusVal: 16,
        left: 40,
        width: 670,
        height: 1140,
        shadow: true,
        background: '#cacacd',
        shadowColor: 'rgba(0,0,0,.6)',
        line: true
      },
      //....
      {
        type: 'text',
        content: '长按或扫描二维码,查看这条线路',
        color: '#9B9BA1',
        top: 1052,
        left: 224,
        fontSize: 28,
        font: 'PingFangSC-Medium',
      },
      {
        type: 'image',
        path: '/common/images/station-flag.png',
        top: 746,
        left: 80,
        width: 32,
        height: 104
      }
    ]
  }
}

export {
  setShareInfo
}

只需要在几个动态信息改变时,传入这些变化的值即可。

import { setShareInfo } from '../../common/config/share-config';
page({
  onLoad: function() {
    this.setData({
      shareMessageInfoTimeline: setShareInfo('3月7号 下午16:30发车', '腾讯大厦', '平安国际中心', '')
    });
    //...
  },
});

通过 shareMessageInfoTimeline 获取配置信息

<view class="container">
  <mod-share-timeline timelineShow="{{timelineShow}}" picContent="{{shareMessageInfoTimeline}}" bindcloseTimelineShow="closeTimelineShow"/>
</view>

总结

本文对小程序分享所需的基础能力进行了拆分详解,把上述能力进行不同的组合,应该可以满足大部分的分享需求。

比如:

  1. 动态绘制分享给微信好友的分享图片。
  2. 生成并保存小程序海报。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Extjs入门之动态加载树代码
Apr 09 Javascript
Jquery通过JSON字符串创建JSON对象
Aug 24 Javascript
javascript学习总结之js使用技巧
Sep 02 Javascript
JQuery对ASP.NET MVC数据进行更新删除
Jul 13 Javascript
Javascript动画效果(3)
Oct 11 Javascript
深入理解Node.js 事件循环和回调函数
Nov 02 Javascript
浅谈JavaScript find 方法不支持IE的问题
Sep 28 Javascript
vue在手机中通过本机IP地址访问webApp的方法
Aug 15 Javascript
vue单页应用在页面刷新时保留状态数据的方法
Sep 21 Javascript
基于Koa2写个脚手架模拟接口服务的方法
Nov 27 Javascript
javascript实现5秒倒计时并跳转功能
Jun 20 Javascript
JavaScript实现轮播图片完整代码
Mar 07 Javascript
关于JavaScript 数组你应该知道的事情(推荐)
Apr 10 #Javascript
Vue中computed、methods与watch的区别总结
Apr 10 #Javascript
JavaScript 性能提升之路(推荐)
Apr 10 #Javascript
详解vue-cli3 中跨域解决方案
Apr 10 #Javascript
js中数组常用方法总结(推荐)
Apr 09 #Javascript
JS隐藏号码中间4位代码实例
Apr 09 #Javascript
vue 点击展开显示更多(点击收起部分隐藏)
Apr 09 #Javascript
You might like
手冲咖啡应该是现代精品咖啡店的必备选项吗?
2021/03/03 冲泡冲煮
Http 1.1 Etag 与 Last-Modified提高php效率
2008/01/10 PHP
ThinkPHP开发--使用七牛云储存
2017/09/14 PHP
PHP面向对象五大原则之单一职责原则(SRP)详解
2018/04/04 PHP
使用jQuery简化Ajax开发 Ajax开发入门
2009/10/14 Javascript
javascript使用activex控件的代码
2011/01/27 Javascript
屏蔽网页右键复制和ctrl+c复制的js代码
2013/01/04 Javascript
JS实现随机化快速排序的实例代码
2013/08/01 Javascript
js Dialog 去掉右上角的X关闭功能
2014/04/23 Javascript
一个JavaScript操作元素定位元素的实例
2014/10/29 Javascript
原生javascript实现图片弹窗交互效果
2015/01/12 Javascript
JavaScript中的对象与JSON
2015/07/03 Javascript
原生 JS Ajax,GET和POST 请求实例代码
2016/06/08 Javascript
jQuery插件HighCharts绘制2D金字塔图效果示例【附demo源码下载】
2017/03/09 Javascript
微信小程序利用co处理异步流程的方法教程
2017/05/20 Javascript
JavaScript之Map和Set_动力节点Java学院整理
2017/06/29 Javascript
Angular中支持SCSS的方法
2017/11/18 Javascript
javascript判断一个变量是数组还是对象
2019/04/10 Javascript
关于JS解构的5种有趣用法
2019/09/05 Javascript
[04:38]完美世界携手游戏风云打造 卡尔工作室饰品系统篇
2013/04/25 DOTA
[01:51]2018年度CS GO最具人气外援-完美盛典
2018/12/16 DOTA
python编写网页爬虫脚本并实现APScheduler调度
2014/07/28 Python
python 实现将多条曲线画在一幅图上的方法
2019/07/07 Python
pandas-resample按时间聚合实例
2019/12/27 Python
Python Sphinx使用实例及问题解决
2020/01/17 Python
python 如何引入协程和原理分析
2020/11/30 Python
CSS3 实现的缩略图悬停效果
2020/12/09 HTML / CSS
客服端调用EJB对象的几个基本步骤
2012/01/15 面试题
婚礼秀策划方案
2014/05/19 职场文书
反对四风自我剖析材料
2014/10/07 职场文书
2016年大学光棍节活动总结
2016/04/05 职场文书
Memcached介绍及php-memcache扩展安装
2021/04/01 PHP
mysql 8.0.24版本安装配置方法图文教程
2021/05/12 MySQL
MySQL中CURRENT_TIMESTAMP的使用方式
2021/11/27 MySQL
Python可视化学习之matplotlib内置单颜色
2022/02/24 Python
shell进度条追踪指令执行时间的场景分析
2022/06/16 Servers