业务场景

二轮充电业务中,用户充电完成后在订单详情页展示订单相关信息,用户点击分享按钮唤起微信小程序分享菜单,将生成的图片海报分享给微信好友或者下载到本地,好友可通过扫描海报中的二维码加群领取优惠。

使用场景及功能:微信小程序 生成海报图片 分享好友 下载图片

使用技术:Taro vue vant canvas

实现效果图

重点步骤拆分

1、封装一个海报分享组件 poster-share.vue

2、用canvas画图,将背景图、费用、二维码等信息绘制在一张图上,其中费用、二维码是动态获取的

3、生成一张本地缓存图片

4、唤起微信分享功能,实现分享和下载功能

重点步骤有了,那么就开干吧!

核心代码实现

1、模版部分

需要一个画布dom用来绘制图片,一个用来存放生成图片的dom

问:canvasId为什么需要动态生成呢?

答:避免一个页面中使用多个组件引起的canvasId重复问题

<template>
<div class="poster-share__content">
<!-- canvas生成的海报图片 -->
<img
v-if="posterImg"
class="poster-share__content--img"
mode="aspectFit"
:src="posterImg"
>
<!-- 分享海报canvas绘制部分 -->
<canvas
class="poster-share__content--cvs"
:canvas-id="canvasId"
></canvas>
</div>
</template>

2、样式部分

该业务场景下,不能让用户看到画布,但是设置canvas的display为none将不能进行绘制,会报如下错误,导致绘制失败。

实现方式:采用定位的方式,将canvas定位到可视区域外,具体代码如下。

.poster-share__content {
position: absolute;
right: -9999px;
top: -9999px;
width: 560px;
height: 852px;
opacity: 0;
z-index: -1; &--img {
width: 100%;
height: 100%;
} &--cvs {
width: 100%;
height: 100%;
}
}

3、核心js部分

开始写核心实现啦~

父组件传参控制子组件是否开始绘制,子组件绘制完成后通知父组件改变状态。

  name: 'CpPosterShare',
model: {
prop: 'value',
event: 'update:value',
},
props: {
value: {
type: Boolean,
default: false,
},
config: {
type: Object,
default: () => ({}),
},
},
data () {
return {
isDraw: false, // 是否开始绘制海报
posterImg: '', // 生成的海报图片地址
canvasId: `canvasId${ Math.random() }`,
screenWidth: null, // 屏幕宽度
}
},
watch: {
value: {
handler (val) {
this.isDraw = val
},
immediate: true,
},
isDraw (val) {
this.$emit('update:value', val)
if (val) {
this.init()
}
},
},

首先,我们做的是一个小程序,将图片放在小程序源码中会加大包的体积,需要从网络上下载图片,因此需要封装一个公共的方法来获取图片的信息。Taro提供getImageInfo方法返回图片的原始宽高、本地路径等信息。

// 加载图片
loadImg (src) {
return newPromise((resolve, reject) => {
Taro.getImageInfo({
src,
}).then((res) => {
resolve({ ...res })
}).catch((err) => {
reject(err)
})
})
}

该业务场景中涉及绘制多张图片,包括背景图片和二维码图片,需要将多张图片都load完成后才能开始绘制。

const promiseParams = [this.loadImg(BgImage), this.loadImg(QRcode)]
const promiseAll = Promise.all(promiseParams.map((item) =>item.catch(() =>null))) promiseAll.then((res) => {
this.draw(res)
}).catch((err) => {
console.log(err)
})

开始绘制啦~

创建canvas绘图上下文CanvasContext对象,调用Taro提供的方法Taro.createCanvasContext(canvasId)绘制背景图、绘制价格、绘制二维码,这里就不一一赘述了。全部绘制完成后,将画布中的内容导出生成图片,Taro提供了canvasToTempFilePath方法,需要在draw()回调中调用才能保证图片导出成功,返回生成图片的临时路径。

ctx.draw(false, () => {
Taro.canvasToTempFilePath({
canvasId:this.canvasId,
}).then((res) => {
this.posterImg = res.tempFilePath // 唤起分享菜单
this.showShareImageMenu()
}).catch((err) => {
console.log('海报生成失败', err)
Taro.showToast({
title: '海报生成失败',
icon: 'error',
})
}).finally(() => {
Taro.hideLoading()
this.isDraw = false
})
})

本地图片生成成功后,唤起微信提供的分享菜单弹窗,可以将图片发送给朋友、收藏、保存到相册。Taro提供showShareImageMenu方法唤起分享菜单弹窗,入参为本地图片路径。

showShareImageMenu () {
if (Taro.showShareImageMenu) {
Taro.showShareImageMenu({
path:this.posterImg,
}).then().catch((err) => {
console.log(err)
const { errMsg } = err
// 取消操作 errMsg === 'showShareImageMenu:fail cancel'
// 拒绝授权 errMsg: "showShareImageMenu:fail auth deny"
if (errMsg === 'showShareImageMenu:fail auth deny') {
authorize({
scope:'writePhotosAlbum',
showModal:true,
authName:'保存图片到相册',
success: () => {
this.downloadImg()
},
})
}
}).finally(() => {
this.isDraw = false
})
} else {
Taro.showToast({
title:'小程序版本不支持该功能',
icon:'error',
})
}
}

用户点击发送给朋友,会调起微信对话框,将生成的海报图片粘贴分享给朋友;

点击收藏,会将海报图片添加到收藏列表中,方便下次查看;

点击保存到相册,会唤起保存图片授权弹窗,用户点击允许,会将海报图片保存在本地相册中。

如果用户在保存图片授权弹窗中第一次点击拒绝,之后再次点击分享下载时,需要有授权提示弹窗,提示用户是否打开设置去授权,具体展示如下。

Taro提供Taro.openSetting方法调起小程序设置页面,用户开启“添加到相册”授权后成功后,调用Taro提供的下载图片的方法Taro.saveImageToPhotosAlbum将图片下载到本地。

授权提示弹窗 设置页面 下载提示

其中判断用户是否开启授权的方法具体实现如下:

/**
* 权限获取流程
* @param scope 权限英文名称
* @param success 授权成功的回调
* @param fail 授权失败的回调
* @param showModal 授权失败是否展示对话框提示
* @param authName 授权失败是否展示对话框提示展示的授权名称
* // 例子:开启用户的相册权限
authorize({
scope: 'writePhotosAlbum',
showModal: true,
authName: '保存图片到相册',
success () {
console.log('授权成功')
},
})
*/
export async function authorize (options) {
const {
scope, success, fail, showModal = false, authName = '',
} = options
try {
const scopeName = `scope.${ scope }`
const auth = await Taro.getSetting()
if (!auth.authSetting[scopeName]) {
Taro.authorize({ scope: scopeName }).then((res) => {
if (res.errMsg === 'authorize:ok' && success) success()
}, () => {
if (showModal && authName) {
Taro.showModal({
title: '授权提示',
content: `您拒绝了${ authName }权限,是否打开设置去授权?`,
}).then((res) => {
if (res.confirm) {
Taro.openSetting().then((res2) => {
if (res2.authSetting[scopeName] && success) {
success()
} else if (fail) {
fail()
}
})
} else {
fail && fail()
}
}).catch((res) => {
fail && fail(res)
})
} else {
fail && fail()
}
})
} else {
success && success()
}
} catch (err) {
fail && fail(err)
}
}

至此,具体实现完结撒花~ 可以将组件用到页面中了

组件引用

<poster-share
v-model="draw" // 是否开始绘制海报海报
config="config" // 海报配置信息
/>

问题记录

在开发过程中遇到了一些问题,记录一下

现象:点击分享,生成canvas图片。开发者工具上每次都正常,ios机每次都正常,部分安卓机每次都正常,部分安卓机,点击分享之后取消,操作多次,有几次会生成图片失败

报错信息:"errMsg": "canvasToTempFilePath:fail :create bitmap failed"

错误定位解决:canvas需要一直显示,不能有display:none的情况

作者:京东零售 张梦雨

内容来源:京东云开发者社区

使用taro+canvas实现微信小程序的图片分享功能的更多相关文章

  1. 微信小程序裁剪图片成圆形

    代码地址如下:http://www.demodashi.com/demo/14453.html 前言 最近在开发小程序,产品经理提了一个需求,要求微信小程序换头像,用户剪裁图片必须是圆形,也在gith ...

  2. 微信小程序实现图片是上传、预览功能

    本文实例讲述了微信小程序实现图片上传.删除和预览功能的方法,分享给大家供大家参考,具体如下: 这里主要介绍一下微信小程序的图片上传图片删除和图片预览 1.可以调用相机也可以从本地相册选择 2.本地实现 ...

  3. 微信小程序仿朋友圈功能开发(发布、点赞、评论等功能)

    微信小程序仿朋友圈功能开发(发布.点赞.评论等功能) 1.项目分析 项目整体分为三个部分 发布 展示 详情页 graph LR 朋友圈发布 --内容发布--> 内容展示 内容展示 --点击展示卡 ...

  4. 微信小程序 base64 图片 canvas 画布 drawImage 实现

    在微信小程序中 canvas drawImage API 传入的第一个参数是 imageResource 图片资源路径,这个参数通常由从相册选择图片 wx.chooseImage 或 wx.getIm ...

  5. 微信小程序之生成图片分享 二维码分享 canvas绘制

    如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 添加画布 首先,在小程序里进行绘图操作需要用到<canvas>组件,步骤大致分为以 ...

  6. 用Taro做个微信小程序Todo, 小白工作记录

    微信小程序框架: Taro 做微信小程序的框架, 几个比较主流的: 官方的WePY: https://tencent.github.io/wepy/document.html#/ 美团的mpvue: ...

  7. 用Taro写一个微信小程序(一)——开始一个项目

    一.Taro简介 1.名字由来 Taro['tɑ:roʊ],泰罗·奥特曼,宇宙警备队总教官,实力最强的奥特曼. 2.taro是什么 Taro 是一个开放式跨端跨框架解决方案,支持使用 React/Vu ...

  8. 微信小程序之生成图片分享

    通过社交软件分享的方式来进行营销小程序,是一个常用的运营途径.小程序本身支持直接将一个小程序的链接卡片分享至微信好友或微信群,然后别人就可以通过点击该卡片进入该小程序页面.但是小程序目前不支持直接分享 ...

  9. 微信小程序首次官方分享的纪要

    先交代备注: 这次有关小程序的分享只有技术的 QA环节,其他如产品.入口.流量.与公众号的整合等等,回答都是暂时无法给出答案或不确定: 小程序最终发布时间官方也还未确定,不过说应该就是近期: 小程序的 ...

  10. 微信小程序产品定位及功能介绍

    产品定位及功能介绍 微信小程序是一种全新的连接用户与服务的方式,它可以在微信内被便捷地获取和传播,同时具有出色的使用体验. 小程序注册 注册小程序帐号 在微信公众平台官网首页(mp.weixin.qq ...

随机推荐

  1. LoadRunner——安装教程以及创建与录制(一)

    theme: channing-cyan 1. loadrunner12|loadrunner12官方版下载(附安装教程)+网盘下载+汉化包 CSDN下载及安装教程: https://blog.csd ...

  2. spring aop切面说明

    execution:处理Join Point的类型,例如call.execution (* android.app.Activity.on**(..)):这个是最重要的表达式,第一个*表示返回值,*表 ...

  3. (1)入门MasaFramework教程

    (1)入门MasaFramework教程 首先了解一下MasaFramework是什么 MasaFramework是一个基于.Net6.0的后端框架, 可以被用于开发Web应用程序.WPF项目.控制台 ...

  4. 什么是Markdown

    什么是markdown? Markdown是一种轻量级标记语言,它允许人们使用已读一些的纯文本格式编写文档,然后转换成有效的XHTML(或者HTML)文档.这种语言吸收了很多在电子邮件中已有的纯文本标 ...

  5. C++温故补缺(十九):atomic类

    atomic 参考:c++11 多线程(3)atomic 总结 - 简书.c++11 atomic Npgw的博客.C++11 并发指南系列 - Haippy - 博客园. atomic_flag a ...

  6. .NET周报 【3月第3期 2023-03-19】

    国内文章 记一次 .NET某汽车零件采集系统 卡死分析 https://www.cnblogs.com/huangxincheng/p/17214154.html 前段时间有位朋友在微信上找到我,说他 ...

  7. 能让Java开发者提高效率的10个工具

    ​ Java受到全球百万计开发者的追捧,已经演变为一门出色的编程语言.最终,这门语言随着技术的变化,不断的被改善以迎合变化的市场需求. 无论你是否拥有一家科技公司,软件已经成为几乎每一个企业不可或缺的 ...

  8. 协程 + epoll 的两个小例子

    getcontext/setupcontext/swapcontext/setcontext 方式的协程实现 #include <stdio.h> #include <stdlib. ...

  9. Java面试——TCP与HTTP

    更多内容,移步 IT-BLOG 一.Session 和 Cookie 的区别 [1]Cookie 保存在客户端,未设置存储时间的 Cookie,关闭浏览器会话 Cookie 就会被删除:设置了存储时间 ...

  10. 最简单Openwrt ipv6配置,局域网WAN6中继模式获取原生ipv6地址

    条件 condition wan 和 wan6 是默认配置     Wan and wan6 are the default configurations 同时wan6可以获取到原生IPv6     ...