微信小程序基于Taro的分享图片功能实践详解


Posted in Javascript onJuly 12, 2019

前言

在各种小程序(微信、百度、支付宝)、H5、NativeApp 纷纷扰扰的当下,给大家强烈安利一款基于React的多终端开发利器:京东Taro(泰罗·奥特曼),Taro致力于多终端统一解决方案,一处代码,多处运行。

Taro支持以React语言开发小程序,支持CSS预处理器,支持实时编译更新,支持NPM,等等等等,简直不要太爽!

微信小程序分享图片功能是经常在小程序业务中出现的,比如学习打卡分享,推广会员分享,推广商品分享等等。因为小程序是不支持直接分享图片到朋友圈的,一般操作为:

  • 生成包含小程序码(当前也可以是其他特定的信息)的图片;
  • 用户点击保存图片,下载到本地,再发布到朋友圈;
  • 其他用户长按识别该小程序码,进入当前小程序。

今天胡哥给大家分享下,基于Taro框架实现微信小程序分享图片功能的实践。

一、搭建Taro项目框架,创建微信小程序

1. 安装taro脚手架工具

npm install -g @tarojs/cli

2. 初始化taro项目

taro init taro-img-share

3. 编译项目,开启Dev模式,生成小程序 -- dist目录

npm run dev:weapp

4. 微信开发者工具,创建小程序,选择项目根目录为taro-img-share下的dist目录

二、小程序分享图片功能实践 --- 打卡图片分享功能

先上图,再说话

微信小程序基于Taro的分享图片功能实践详解

效果图

微信小程序基于Taro的分享图片功能实践详解

点击保存到相册

这是重点:使用Canvas绘制图片并展示,保存图片到相册

drawImage()方法负责绘制展示,saveCard()方法负责下载图片到相册

src/pages/index/index.js

import Taro, { Component } from '@tarojs/taro'
// 引入对应的组件
import { View, Text, Button, Canvas } from '@tarojs/components'
import './index.scss'

export default class Index extends Component {

 config = {
 navigationBarTitleText: '首页'
 }

 /**
 * 初始化信息
 */
 constructor () {
 this.state = {
  // 用户信息
  userInfo: {},
  // 是否展示canvas
  isShowCanvas: false
 }
 }

 /**
 * getUserInfo() 获取用户信息
 */
 getUserInfo (e) {
 if (!e.detail.userInfo) {
  Taro.showToast({
  title: '获取用户信息失败,请授权',
  icon: 'none'
  })
  return
 }
 this.setState({
  isShowCanvas: true,
  userInfo: e.detail.userInfo
 }, () => {
  // 调用绘制图片方法
  this.drawImage()
 })
 }

 /**
 * drawImage() 定义绘制图片的方法
 */
 async drawImage () {
 // 创建canvas对象
 let ctx = Taro.createCanvasContext('cardCanvas')
 
 // 填充背景色
 let grd = ctx.createLinearGradient(0, 0, 1, 500)
 grd.addColorStop(0, '#1452d0')
 grd.addColorStop(0.5, '#FFF')
 ctx.setFillStyle(grd)
 ctx.fillRect(0, 0, 400, 500)

 // // 绘制圆形用户头像
 let { userInfo } = this.state
 let res = await Taro.downloadFile({
  url: userInfo.avatarUrl
 })
 ctx.save()
 ctx.beginPath()
 // ctx.arc(160, 86, 66, 0, Math.PI * 2, false)
 ctx.arc(160, 88, 66, 0, Math.PI * 2)
 ctx.closePath()
 ctx.clip()
 ctx.stroke()
 ctx.translate(160, 88)
 ctx.drawImage(res.tempFilePath, -66, -66, 132, 132)
 ctx.restore()

 // 绘制文字
 ctx.save()
 ctx.setFontSize(20)
 ctx.setFillStyle('#FFF')
 ctx.fillText(userInfo.nickName, 100, 200)
 ctx.setFontSize(16)
 ctx.setFillStyle('black')
 ctx.fillText('已在胡哥有话说公众号打卡20天', 50, 240)
 ctx.restore()

 // 绘制二维码
 let qrcode = await Taro.downloadFile({
  url: 'https://upload-images.jianshu.io/upload_images/3091895-f0b4b900390aec73.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/258/format/webp.jpg'
 })
 ctx.drawImage(qrcode.tempFilePath, 70, 260, 180, 180)

 // 将以上绘画操作进行渲染
 ctx.draw()
 }

 /**
 * saveCard() 保存图片到本地
 */
 async saveCard () {
 // 将Canvas图片内容导出指定大小的图片
 let res = await Taro.canvasToTempFilePath({
  x: 0,
  y: 0,
  width: 400,
  height: 500,
  destWidth: 360,
  destHeight: 450,
  canvasId: 'cardCanvas',
  fileType: 'png'
 })
 let saveRes = await Taro.saveImageToPhotosAlbum({
  filePath: res.tempFilePath
 })
 if (saveRes.errMsg === 'saveImageToPhotosAlbum:ok') {
  Taro.showModal({
  title: '图片保存成功',
  content: '图片成功保存到相册了,快去发朋友圈吧~',
  showCancel: false,
  confirmText: '确认'
  })
 } else {
  Taro.showModal({
  title: '图片保存失败',
  content: '请重新尝试!',
  showCancel: false,
  confirmText: '确认'
  })
 }
 }

 render () {
 let { isShowCanvas } = this.state
 return (
  <View className='index'>
  <Button onGetUserInfo={this.getUserInfo} openType="getUserInfo" type="primary" size="mini">打卡</Button>
  {/* 使用Canvas绘制分享图片 */}
  {
   isShowCanvas && 
   <View className="canvas-wrap">
    <Canvas 
    id="card-canvas"
    className="card-canvas"
    style="width: 320px; height: 450px"
    canvasId="cardCanvas" >
    </Canvas>
    <Button onClick={this.saveCard} className="btn-save" type="primary" size="mini">保存到相册</Button>
   </View> 
  }
  </View>
 )
 }
}

src/pages/index/index.sass

index.js组件中的css样式

.index {
 display: flex;
 align-items: center;
 justify-content: center;
 height: 100%;
}
.canvas-wrap {
 width: 100%;
 height: 100%;
 background: rgba(0, 0, 0, 0.3);
 position: fixed;
 top: 0;
 left: 0;
 display: flex;
 align-items: center;
 justify-content: center;
 flex-direction: column;
 .btn-save {
 margin-top: 40rpx;
 }
}

注意事项

设置Taro支持ES6的async/await

1.下载@tarojs/async-await

npm install -D @tarojs/async-await

2.app.js中引入

import '@tarojs/async-await'

开发完毕,发布小程序

1.执行打包,生成最终的小程序源码

npm run build:weapp

2.发布小程序

点击微信开发者工具上传按钮,上传小程序,然后在微信小程序平台发布小程序即可。

小结

本文着重介绍了使用Taro实现小程序生成打卡图片,保存相册,分享图片功能的开发原理与实践步骤,各位童鞋可参考并结合自己的实际业务进行扩展开发。

本文并为深入的对不同手机进行图片适配,部分值也是设置的固定值(如填充文字的开始坐标与填充的文字长度、大小),并未做比例响应。需要进一步交流的小伙伴,可以关注胡哥有话说公众号,持续关注相关文章,也可直接在文章留言交流。

无论是使用何种框架如Taro、mpvue、wepy等开发小程序分享图片功能,原理都是一样的,只不过是在调用方法以及处理逻辑时需要进行响应的小调整

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

Javascript 相关文章推荐
js禁止页面使用右键(简单示例代码)
Nov 13 Javascript
当json键为数字时的取值方法解析
Nov 15 Javascript
浅谈Javascript 执行顺序
Dec 18 Javascript
一个JavaScript去除字符串末尾的空白实例代码
Sep 22 Javascript
jQuery on方法传递参数示例
Dec 09 Javascript
Highcharts入门之简介
Aug 02 Javascript
jQuery+PHP实现上传裁剪图片
Jun 29 jQuery
微信小程序数据统计和错误统计的实现方法
Jun 26 Javascript
vue遍历生成的输入框 绑定及修改值示例
Oct 30 Javascript
微信sdk实现禁止微信分享(使用原生php实现)
Nov 15 Javascript
ant-design-vue 快速避坑指南(推荐)
Jan 21 Javascript
vue 动态添加的路由页面刷新时失效的原因及解决方案
Feb 26 Vue.js
小程序实现悬浮搜索框
Jul 12 #Javascript
小程序实现搜索框功能
Mar 26 #Javascript
iview的table组件自带的过滤器实现
Jul 12 #Javascript
es6中比较有用的7个技巧小结
Jul 12 #Javascript
echarts大屏字体自适应的方法步骤
Jul 12 #Javascript
javascript实现简易聊天室
Jul 12 #Javascript
简单了解vue中父子组件如何相互传递值(基础向)
Jul 12 #Javascript
You might like
PHP中的CMS的涵义
2007/03/11 PHP
php 信息采集程序代码
2009/03/17 PHP
PHP函数getenv简介和使用实例
2014/05/12 PHP
ThinkPHP3.1新特性之查询条件预处理简介
2014/06/19 PHP
PHP函数实现分页含文本分页和数字分页
2014/10/23 PHP
php针对cookie操作的队列操作类实例
2014/12/10 PHP
PHP7创建销毁session的实例方法
2020/02/03 PHP
TP5框架使用QueryList采集框架爬小说操作示例
2020/03/26 PHP
js类中的公有变量和私有变量
2008/07/24 Javascript
jQuery(js)获取文字宽度(显示长度)示例代码
2013/12/31 Javascript
基于jQuery通过jQuery.form.js插件实现异步上传
2015/12/13 Javascript
详述JavaScript实现继承的几种方式(推荐)
2016/03/22 Javascript
JS简单实现禁止访问某个页面的方法
2016/09/13 Javascript
BootStrapValidator初使用教程详解
2017/02/10 Javascript
使用jQuery和ajax代替iframe的方法(详解)
2017/04/12 jQuery
vue mounted组件的使用
2018/06/18 Javascript
Vue下路由History模式打包后页面空白的解决方法
2018/06/29 Javascript
Python中的filter()函数的用法
2015/04/27 Python
Python2.7编程中SQLite3基本操作方法示例
2017/08/09 Python
python+selenium 定位到元素,无法点击的解决方法
2019/01/30 Python
python实现五子棋游戏(pygame版)
2020/01/19 Python
Python中的 ansible 动态Inventory 脚本
2020/01/19 Python
基于Python3.6中的OpenCV实现图片色彩空间的转换
2020/02/03 Python
python实现猜拳游戏
2020/03/04 Python
pandas分组聚合详解
2020/04/10 Python
如何用Matlab和Python读取Netcdf文件
2021/02/19 Python
CSS3 transition 实现通知消息轮播条
2020/10/14 HTML / CSS
蒂娜商店:Tiina the Store
2019/12/07 全球购物
俄罗斯鲜花递送:AMF
2020/04/24 全球购物
企业文化标语大全
2014/06/10 职场文书
党员学习中共十八大报告思想汇报
2014/09/15 职场文书
法人单位适用的授权委托书
2014/09/19 职场文书
2014年医务科工作总结
2014/12/18 职场文书
欠条样本
2015/07/03 职场文书
2016年万圣节家长开放日活动总结
2016/04/05 职场文书
Mysql服务添加 iptables防火墙策略的方案
2021/04/29 MySQL