创建移动应用,配置证书等步骤,在此不表
具体见wx.miniapp.shareMiniProgramMessage中说明
一、分享配置写法
小程序写法
Page({ onShareAppMessage() { const promise = new Promise(resolve => { setTimeout(() => { resolve({ title: '自定义转发标题' }) }, 2000) }) return { title: '自定义转发标题', path: '/page/user?id=123', promise } } })
donut写法
Page({ onShareAppMessage() { const promise = new Promise(resolve => { setTimeout(() => { resolve({ userName: '小程序原始id', path: 'pages/index/index', title: '标题', imagePath: '/pages/thumb.png', webpageUrl: 'www.qq.com', withShareTicket: true, miniprogramType: 0, scene: 0, }) }, 2000) }) return { userName: '小程序原始id', path: 'pages/index/index', title: '标题', imagePath: '/pages/thumb.png', webpageUrl: 'www.qq.com', withShareTicket: true, miniprogramType: 0, scene: 0, promise } } })
很明显可以发现,
donut
只有2点不一样- 少了一些
userName
和webpageUrl
等配置 - 有一些配置项的转换,如
imageUrl
转换为imagePath
- 少了一些
上述两点只需要在某个全局的地方加上即可
统一兼容方式
注意在这需要使用donut的条件编译(或者在require处使用条件编译也可)
否则微信小程序中也会有这段不需要的代码
重写
Page
和Component
,使用handleAppShareInfo
拦截onShareAppMessage
方法const originalPage = Page; Page = function (e) { const app = getApp(); if (e.onShareAppMessage) { e.onShareAppMessage = handleAppShareInfo(e.onShareAppMessage); } return originalPage(e); }; const originalComponent = Component; Component = function (e) { if (e.methods && e.methods.onShareAppMessage) { e.methods.onShareAppMessage = handleAppShareInfo(e.methods.onShareAppMessage); } return originalComponent(e); };
添加小程序端缺失的配置
function appShareInfoAdapter(result) { return Object.assign({}, { userName: '小程序原始id', description: '', imagePath: res.imageUrl || '', webpageUrl: 'https://www.qq.com', withShareTicket: false, miniprogramType: 0, scene: 0, }, result, { imageUrl: void 0, }) } function handleAppShareInfo(originalShare) { return function (...args) { const originResult = originalShare.apply(this, args) const result = appShareInfoAdapter(originResult) if (result.promise) { result.promise = result.promise.then(appShareInfoAdapter) } return result }; }
二、图片大小限制
- 之后运行发现,有时候会报错图片超过128KB限制(具体见微信文档安卓/IOS),得先将大于
128kb
的图片压缩 - 但是对
png
文件进行wx.compressImage
无效 这是一个微信官方已确认的bug,无法压缩png文件
此处提到的
把thumbData的转换逻辑改下
,对应到我们开发者,
是需要project.miniapp.json
文件中的sdkVersion
改成1.3.7-beta.2-656
(或者大于此版本)
所以在图片大于128kb的情况下,得把分享图片转换成jpg再进行压缩,以下是具体代码
代码模块内canvas变量&128kb限制常量
/** @type { WechatMiniprogram.FileSystemManager } */ let globalFileSystemManager const size128kb = 131072 function getFileSystemManager() { return globalFileSystemManager || (globalFileSystemManager = wx.getFileSystemManager()) }
因为app分享只能使用本地路径,所以需要实现转换本地路径逻辑
/** * 获取分享图本地路径 * @param { string } imagePath 图片路径 * @returns { Promise<string> } */ function getShareImageLocalPath(imagePath) { return imagePath.startsWith('http') ? new Promise((resolve) => { wx.downloadFile({ url: imagePath, success(res) { resolve(res.tempFilePath) }, fail() { resolve('') } }) }) : imagePath }
png转换jpg逻辑
/** * 将图片转换为jpg格式 * @param { string } imagePath 非jpg图片路径 * @param { WechatMiniprogram.GetImageInfoSuccessCallbackResult } imageInfo * @returns { Promise<string> } */ async function function convert2JPG(imagePath, imageInfo) { const { width, height } = imageInfo const canvas = wx.createOffscreenCanvas({ type: '2d', width, height }) const context = canvas.getContext('2d') const image = canvas.createImage() await new Promise(resolve => { image.onload = resolve image.src = imagePath }) context.clearRect(0, 0, width, height) context.drawImage(image, 0, 0, width, height) /** @type { Promise<string> } */ return new Promise(resolve => { // #if ANDROID wx.canvasToTempFilePath({ width, height, destWidth: width, destHeight: height, canvas, fileType: 'jpg', quality: 1, success(res) { resolve(res.tempFilePath) }, fail() { resolve('') } }) // #elif IOS const imagePath = `${wx.env.USER_DATA_PATH}/temp-${Date.now()}.jpg` getFileSystemManager().writeFile({ filePath: imagePath, data: canvas.toDataURL('image/jpeg').replace(/^data:image\/\w+;base64,/, ''), encoding: 'base64', success() { resolve(imagePath) }, fail() { resolve('') }, }) // #endif }) }
压缩图片
/** * 压缩分享图片 * @param { string } imageLocalPath 本地图片路径 * @param { boolean } skipPngCheck 跳过图片格式检查 * @returns { Promise<string> } */ async function compressImageShareImage(imageLocalPath, skipPngCheck = false) { /** @type { number } */ const imageSize = await new Promise(resolve => { getFileSystemManager().getFileInfo({ filePath: imageLocalPath, success(res) { resolve(res.size) }, fail() { resolve(0) } }) }) if (imageSize <= size128kb) { return imageLocalPath } if (!skipPngCheck) { /** @type { WechatMiniprogram.GetImageInfoSuccessCallbackResult } */ const imageInfo = await new Promise(resolve => wx.getImageInfo({ src: imageLocalPath, success: resolve, fail() { resolve({ width: 0, height: 0 }) } })) // wx.compressImage无法压缩png图片 // 官方开发人员已经确认的bug,并且暂时无法修改 // 所以,先转换成jpg再进行压缩 if (imageInfo.type === 'png') { const jpgImage = await convert2JPG(imageLocalPath, imageInfo) // 转换之后,再走一次compressImageShareImage里面的imageSize逻辑 // 如果jpgImage比128kb还小,就不需要再压缩了 return compressImageShareImage(jpgImage, true) } } return new Promise(resolve => wx.compressImage({ src: imageLocalPath, quality: Math.max(1, Math.floor(100 * size128kb / imageSize)), success(res) { resolve(res.tempFilePath) }, fail() { resolve('') } })) }
修改onShareAppMessage返回值
function handleAppShareInfo(originalShare) { return function (...args) { const originResult = originalShare.apply(this, args) const result = appShareInfoAdapter(originResult) result.promise = ( result.promise ? result.promise.then(appShareInfoAdapter) : Promise.resolve(result) ).then(async res => { /** @type { { imagePath: string } } */ const { imagePath } = res /** @type { string } */ const imageLocalPath = await getShareImageLocalPath(imagePath) res.imagePath = await compressImageShareImage(imageLocalPath) return res }) return result }; }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。