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


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 相关文章推荐
Web前端设计模式  制作漂亮的弹出层
Oct 29 Javascript
原生Js与jquery的多组处理, 仅展开一个区块的折叠效果
Jan 09 Javascript
js,jQuery 排序的实现代码,网页标签排序的实现,标签排序
Apr 27 Javascript
javascript开发随笔二 动态加载js和文件
Nov 25 Javascript
jquery让指定的元素闪烁显示的方法
Mar 17 Javascript
jquery实现鼠标点击后展开列表内容的导航栏效果
Sep 14 Javascript
javascript学习小结之prototype
Dec 03 Javascript
jQuery简单设置文本框回车事件的方法
Aug 01 Javascript
AngularJS 工作原理详解
Aug 18 Javascript
微信小程序实现页面下拉刷新和上拉加载功能详解
Dec 03 Javascript
vscode 配置vue+vetur+eslint+prettier自动格式化功能
Mar 23 Javascript
JavaScript中isPrototypeOf函数
Nov 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
执行、获取远程代码返回:file_get_contents 超时处理的问题详解
2013/06/25 PHP
解析WordPress中函数钩子hook的作用及基本用法
2015/12/22 PHP
PHP实现RSA签名生成订单功能【支付宝示例】
2017/06/06 PHP
Three.js源码阅读笔记(物体是如何组织的)
2012/12/27 Javascript
Ajax提交与传统表单提交的区别说明
2014/02/07 Javascript
JS动态加载当前时间的方法
2015/02/09 Javascript
JS+CSS实现带有碰撞缓冲效果的竖向导航条代码
2015/09/15 Javascript
Nodejs的express使用教程
2015/11/23 NodeJs
AngularJs Managing Service Dependencies详解
2016/09/02 Javascript
使用Angular缓存父页面数据的方法
2017/01/03 Javascript
vue获取input输入值的问题解决办法
2017/10/17 Javascript
layui点击导航栏刷新tab页的示例代码
2018/08/14 Javascript
vue路由传参三种基本方式详解
2019/12/09 Javascript
Python实现提取谷歌音乐搜索结果的方法
2015/07/10 Python
python实现字符串加密 生成唯一固定长度字符串
2019/03/22 Python
Python如何优雅获取本机IP方法
2019/11/10 Python
tensorflow与numpy的版本兼容性问题的解决
2021/01/08 Python
PyCharm2020.3.2安装超详细教程
2021/02/08 Python
用css3制作纸张效果(外翻卷角)
2013/02/01 HTML / CSS
纯CSS3单页切换导航菜单界面设计的简单实现
2016/08/16 HTML / CSS
canvas仿写贝塞尔曲线的示例代码
2017/12/29 HTML / CSS
Hanky Panky官方网站:内衣和睡衣
2019/07/25 全球购物
斯洛伐克电子产品购物网站:DATART
2020/04/05 全球购物
绩效工资分配方案
2014/01/18 职场文书
《莫高窟》教学反思
2014/02/25 职场文书
外语系大学生自荐信范文
2014/03/01 职场文书
2014年端午节活动方案
2014/03/11 职场文书
2014年祖国生日寄语
2014/09/19 职场文书
学校领导班子四风问题整改意见
2014/10/02 职场文书
试用期工作表现自我评价
2015/03/06 职场文书
甲午风云观后感
2015/06/02 职场文书
海上钢琴师观后感
2015/06/03 职场文书
大卫科波菲尔读书笔记
2015/06/30 职场文书
个人合作协议范本
2015/08/06 职场文书
python之django路由和视图案例教程
2021/07/26 Python
Nginx内网单机反向代理的实现
2021/11/07 Servers