小程序五花八门的分享

1,577 阅读6分钟

常见小程序分享分为:

  1. 分享给朋友
  2. 分享到朋友圈
  3. 短链接分享
  4. 生成二维码分享

准备

页面1:pages/from/from 用来触发分享

页面2:pages/to/to 模拟打开分享后得页面

分享给朋友

右上角分享

页面中定义 onShareAppMessage 方法。不定义此方法,右上角分享给朋友置灰不可用。

onShareAppMessage 方法 return 一个对象,用于自定义转发内容:

    onShareAppMessage() {
        const promise = new Promise(resolve => {
            setTimeout(() => {
                resolve({
                    title: 'promise定义的转发标题'
                })
            }, 5000) // 超出3秒,使用默认定义
        });
        return {
            title: '转发标题',
            path: '/pages/to/to', // 转发后打开的路径,默认为当前页面,必须以/开头的完整路径
            imageUrl: 'http://img.netbian.com/file/2024/0819/232435idR4n.jpg', // 分享图片,默认使用截图
            promise //如果该参数存在,则以 resolve 结果为准,如果三秒内不 resolve,分享会使用上面传入的默认参数
        }
    }

传递参数:

    onShareAppMessage() {
        return {
            title: '转发标题',
            path: '/pages/to/to?name=Tony&age=18', // 直接在路径上添加参数
        }
    }

接收参数:

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad(options) {
        console.log('to页面接受参数',options)
    },

自定义按钮

<button open-type="share">分享</button>

当然真实开发中我们很少能接受这么丑的按钮。我们可以使用 position:absolute 将按钮放到 UI 设计的按钮上,并且通过opacity: 0 设置透明不可见。

其余部分和右上角分享一样,在此不做赘述。

分享到朋友圈

右上角分享

在页面开启了 onShareAppMessage 的前提下,再在页面中定义 onShareTimeline 方法。不定义此方法,右上角分享到朋友圈置灰不可用。

onShareTimeline 方法 return 一个对象,用于自定义转发内容(不支持自定义页面路径):

    // 分享朋友圈
    onShareTimeline(){
        return {
            title:"朋友圈列表页面上显示的标题",
            imageUrl: 'http://img.netbian.com/file/2024/0819/232435idR4n.jpg', // 分享图片,默认使用小程序logo
​
        }
    }

传递参数:通过query传递参数

    // 分享朋友圈
    onShareTimeline(){
        return {
            title:"朋友圈列表页面上显示的标题",
            imageUrl: 'http://img.netbian.com/file/2024/0819/232435idR4n.jpg', // 分享图片,默认使用小程序logo
            query:'name=tony&age=19'
        }
    }

接收参数:

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad(options) {
        console.log('from页面接收参数',options);
    },

自定义按钮--暂不支持

目前只支持右上角分享到朋友圈,不支持自定义按钮分享到朋友圈。

单页面模式

点击分享到朋友圈的链接打开小程序时,进入的是小程序单页模式

在单页面模式中,页面底部有固定的操作栏进入小程序。进入正式小程序后,朋友圈传递的参数依旧在 option 中,不会丢失。

可以通过wx.getLaunchOptionsSync().scene获取场景值为1154,判断打开方式是朋友圈内打开“单页模式” ,由此来进行页面适配等操作(由于页面固定有顶部导航栏与底部操作栏,很可能会影响小程序页面的布局)。

点击进入小程序后场景值变为1155,表示:“单页模式”打开小程序。

单页面可实现的交互与接口能力有限,存在限制如下:

  1. 页面无登录态,与登录相关的接口,如 wx.login 均不可用;云开发资源需开启未登录访问方可在单页模式下使用,详见未登录模式
  2. 不允许跳转到其它页面,包括任何跳小程序页面、跳其它小程序、跳微信原生页面
  3. 不允许横屏使用
  4. 若页面包含 tabBartabBar不会渲染,包括自定义 tabBar
  5. 本地存储与小程序普通模式不共用

短链接分享

右上角复制链接

右上角复制链接是微信的默认行为,目前没有找到可以自定义打开页面的方法。

传递参数:

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad(options) {
        this.shortLinkAddQuery();
    },
    /**
     * 绑定分享参数
     */
    shortLinkAddQuery() {
        let query = `queryA=1&queryB=2`;
       
        //监听用户点击右上角菜单的「复制链接」按钮时触发的事件。本接口为 Beta 版本,暂只在 Android 平台支持。
        wx.onCopyUrl(() => {
            return {
                query
            }
        })
    },
        
    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload() {
        // 取消绑定分享参数,防止影响其它页面。
        wx.offCopyUrl()
    },

接收参数:

​
    /**
     * 生命周期函数--监听页面加载
     */
    onLoad(options) {
        console.log('from页面接收参数',options);
    },

自定义按钮

注意:pageUrl必须是已经发布的小程序存在的页面,否则生成链接会失败。

生成短链接的接口需要后端调用,所以需要后端提供接口/api/get/link

<button bindtap="getShareLink">复制链接</button>
    /**
     * 点击获取短链
     */
    getShareLink() {
        const params = {
            pageUrl: `pages/find/find?a=Tony&b=18`, //通过 Short Link 进入的小程序页面路径,必须是已经发布的小程序存在的页面,可携带 query,最大1024个字符
            pageTitle: '自定义标题',
        };
        //隐藏弹出框
        wx.showLoading({
            title: '链接生成中',
            mask: 'true'
        })
        wx.request(`/api/get/link`, "POST", params).then(res => {
            wx.hideLoading();
​
            if (res.status == '200') {
                if (res.data) {
                    wx.setClipboardData({
                        data: res.data,
                        success: function (res) {
​
                        }
                    })
                } else {
                    wx.showToast({
                        icon: 'error',
                        title: '请稍后再试',
                    })
                }
            } else {
                wx.showToast({
                    icon: 'error',
                    title: '请稍后再试',
                })
            }
        })
​
    },

接收参数依旧在options中。

二维码分享

通过后台接口可以获取小程序任意页面的小程序码,扫描该小程序码可以直接进入小程序对应的页面

获取二维码

获取小程序二维码需要后端调用微信官方接口,所以需要后端支持。传参方式也就自然和后端协商了。

需要注意,只能生成已经发布的小程序的二维码。

// getQrCode函数在后续
<button bindtap="getQrCode">生成二维码</button>
<image class="qrCode" wx:if="{{qrCode}}" src="{{qrCode}}" mode=""/>

普通展示二维码

    // 生成海报
    getQrCode() {
        let params = {
            page: `pages/to/to`,
            params: `queryA=a&queryB=b`
        }
        wx.showLoading({
            title: '图片生成中',
            mask: true
        });
        wx.request('/getCodeRul', 'post', params).then(res => {
            if (res.status == '2000') {
                const qrCodeImg = `data:image/png;base64,${res.data}`
                console.log('地址', qrCodeImg)
                this.setData({
                    qrCode: qrCodeImg
                });
                wx.hideLoading();
            }
        })
    },

二维码长按操作

so easy,添加show-menu-by-longpres属性即可弹出

image.png

<image show-menu-by-longpress="{{true}}" class="qrCode" wx:if="{{qrCode}}" src="{{qrCode}}" mode=""/>

按钮下载二维码

<button bindtap="downLoadQrcode">下载二维码</button>
downLoadQrcode(){
        const {qrCode} = this.data;
        var steam = wx.getFileSystemManager();
            steam.writeFile({
                filePath: wx.env.USER_DATA_PATH + '/poster.png',
                data: qrCode.slice(22),
                encoding: 'base64',
                success: res => {
                    wx.saveImageToPhotosAlbum({
                        filePath: wx.env.USER_DATA_PATH + '/poster.png',
                        success: function () {
                            wx.hideLoading()
                            wx.showModal({
                                title: '保存图片成功',
                                content: '图片已经保存到您的相册',
                                showCancel: false,
                                success: function (res) {},
                                fail: function (res) {},
                                complete: function (res) {},
                            });
                        },
                        fail: function (res) {
                            wx.hideLoading()
                            if (res.errMsg == "saveImageToPhotosAlbum:fail cancel") {
                                wx.showModal({
                                    title: '保存图片失败',
                                    content: '您已取消保存图片到相册!',
                                    showCancel: false
                                });
                            } else {
                                wx.showModal({
                                    title: '提示',
                                    content: '保存图片失败,您可以点击确定设置获取相册权限后再尝试保存!',
                                    complete: function (res) {
                                        if (res.confirm) {
                                            wx.openSetting({}) //打开小程序设置页面,可以设置权限
                                        } else {
                                            wx.showModal({
                                                title: '保存图片失败',
                                                content: '您已取消保存图片到相册!',
                                                showCancel: false
                                            });
                                        }
                                    }
                                });
                            }
                        }
                    })
                },
                fail: err => {
                    console.log(err)
                }
            })
    },

获取参数

由于二维码的参数长度存在限制,若是参数比较长,可以存在后端,扫码时从后端获取:

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
        let scene = decodeURIComponent(options.scene); //"id=1234"
    }

海报展示二维码

  1. 首先准备wxml-to-canvas,详细介绍戳这里。

    <wxml-to-canvas class="widget" ></wxml-to-canvas>
    

    并且让元素在页面内不可见:

    .widget{
        width: 0;
        height: 0;
        overflow: hidden;
        display: block;
        position: fixed;
        left: 0;
        top: 10000%;
        z-index: -1111;
    }
    
  2. 获取wxml-to-canvas实例

        /**
         * 生命周期函数--监听页面加载
         */
        onLoad(options) {
            this.widget = this.selectComponent('.widget')
        },
    
  3. 获取二维码并绘制海报

    const {wxmls,styles} = require('./utils');
    
    Page({
     // 生成海报
    getQrCode() {
        let params = {
            page: `pages/to/to`,
            params: `queryA=a&queryB=b`
        }
        wx.showLoading({
            title: '图片生成中',
            mask: true
        });
        let that = this;
        app.request('/api/getQrcode', 'post', params).then(res => {
            if (res.status == '2000') {
                const qrCodeImg = `data:image/png;base64,${res.data}`
                this.setData({
                    qrCode: qrCodeImg
                });
                const backSrc = 'http://img.netbian.com/file/2024/0819/232435idR4n.jpg';
                const p1 = that.widget.renderToCanvas({
                    wxml: wxmls(qrCodeImg, backSrc),
                    style: styles
                })
                p1.then((res) => {
                    wx.hideLoading();
                    const p2 = that.widget.canvasToTempFilePath()
                    p2.then(res => {
                        console.log('回执图片地址', res);
                        that.setData({
                            src: res.tempFilePath
                        }, function () {
                            wx.hideLoading();
                        })
                    }).catch(fail => {
                        wx.hideLoading();
                        console.log(fail)
                        wx.showToast({
                            icon: 'error',
                            title: '请稍后再试',
                        })
                    })
                }).catch(fail => {
                    wx.hideLoading();
                    wx.showToast({
                        icon: 'error',
                        title: '请稍后再试',
                    })
                })
            }
        })
    },
    })
    
    
  4. wxml 模板和样式

    const wxmls = (erweima, backImg) => {
        return `
        <view class="popbox">
            <image class="backlogo" src="` + backImg + `"/>
            <image class="qrcode" src="` + erweima + `"/>
        </view>
        `
    };
    
    const width = 300,
        height = 455;
    
    const styles = {
        backlogo: {
            position: "relative",
            width,
            height,
        },
    
        qrcode:{
            position:'absolute',
            width:160,
            height:160,
            borderRadius:80,
            bottom:20,
            right:20
        }
    }
    
    module.exports = {
        styles,
        wxmls
    }
    

保存海报

        /**
         * 点击保存二维码
         */
        saveImg() {
            const that = this;
            const p2 = this.widget.canvasToTempFilePath();
            p2.then(res => {
                wx.saveImageToPhotosAlbum({
                    filePath: res.tempFilePath,
                    success(res) {
                        wx.showModal({
                            content: '海报已保存到相册',
                            showCancel: false,
                            confirmText: '确定',
                            confirmColor: '#333',
                            success: function (res) {
                                if (res.confirm) {
                                    //执行成功回调
                                }
                            },
                            fail: function (res) {}
                        })
                    }
                })
            })
        },

海报总结

  1. 海报通过wxmls设置模板,通过styles定义样式,并且每个元素必须设置weightheight 不然不会显示。同时样式只支持部分属性,具体看这里

  2. widget.renderToCanvas({wxml, style}): Promise:渲染到 canvas,传入 wxml 模板 和 style 对象,返回的容器对象包含布局和样式信息。

  3. canvasToTempFilePath({fileType, quality}): Promise:提取画布中容器所在区域内容生成相同大小的图片,返回临时文件地址。

  • fileType 支持 jpgpng 两种格式,quality 为图片的质量,目前仅对 jpg 有效。取值范围为 (0, 1],不在范围内时当作 1.0 处理