当前位置:首页 » 《随便一记》 » 正文

微信小程序插件--wxml-to-canvas(生成图片)

18 人参与  2023年04月05日 16:25  分类 : 《随便一记》  评论

点击全文阅读


一、需求

        项目中要实现一个将图片分享到朋友圈的功能,将生成的海报转成图片保存到手机。用到了wxml-to-canvas插件。

二、官方示例使用方法

        1.安装wxml-to-canvas

npm install --save wxml-to-canvas

        2.JSON 组件声明

{  "usingComponents": {    "wxml-to-canvas": "wxml-to-canvas",  }}

         3.wxml 引入组件

<video class="video" src="{{src}}">  <wxml-to-canvas class="widget"></wxml-to-canvas></video><image src="{{src}}" style="width: {{width}}px; height: {{height}}px"></image>

        4. js 获取实例

const {wxml, style} = require('./demo.js')Page({  data: {    src: ''  },  onLoad() {    this.widget = this.selectComponent('.widget')  },  renderToCanvas() {    const p1 = this.widget.renderToCanvas({ wxml, style })    p1.then((res) => {      this.container = res      this.extraImage()    })  },  extraImage() {    const p2 = this.widget.canvasToTempFilePath()    p2.then(res => {      this.setData({        src: res.tempFilePath,        width: this.container.layoutBox.width,        height: this.container.layoutBox.height      })    })  }})

三、实际项目

        安装、json配置、wxml引入都一样。

        1.wxml

    <wxml-to-canvas class="widget" width="325" height="550"></wxml-to-canvas>       <view class='save flex-center-center' bindtap='preservation'>        保存海报    </view>

        2.js文件

const net = require('../../../common/network.js');//⚠️海报内容和样式const { wxml, style } = require('./canvas.js');//自己封装的微信apiimport wxApi from '../../../common/wxApi';const app = getApp();Page({    /**     * 页面的初始数据     */    data: {    },    /**     * 生命周期函数--监听页面加载     */    onLoad(options) {        wx.showLoading({            title: '海报生成中...',        });        //获取页面初始数据        this.getServerData();    },    getServerData() {        net.posterInfo().then((response) => {            const { name, title, teacher, qr_code, task_id } = response.data;            const { real_name, avatarurl, nickname } = app.globalData.userInfo;            //画海报用到的数据            this.setData({                info: response.data,                avatarurl,                name,                title,                teacher,                qr_code,            });            //注意⚠️:这里是对页面初始渲染            this.widget = this.selectComponent('.widget');            const _wxml = wxml(name, avatarurl, title, teacher, qr_code);            //onload方法里节点没加载完,设置定时器            setTimeout(() => {                //渲染到 canvas,传入 wxml 模板 和 style 对象,返回的容器对象包含布局和样式                                            //信息。                const p1 = this.widget.renderToCanvas({                    wxml: _wxml,                    style,                });                p1.then((res) => {                    this.container = res;                    wx.hideLoading();                });            }, 500);        });    },    preservation() {        // this.widget = this.selectComponent('.widget')        const { task_id } = this.data;        const p2 = this.widget.canvasToTempFilePath();        p2.then((res) => {            //保存到本地相册            wxApi.apiScopeOauth('scope.writePhotosAlbum').then(() => {                wx.saveImageToPhotosAlbum({                    filePath: res.tempFilePath,                    success(res) {                        util.showToast(                            '海报已保存,快去朋友圈分享吧!',                            'none',                            3000                        );                    },                    fail(res) {                        wx.showToast({                            icon: 'error',                            title: '保存图片失败!',                        });                    },                });            });        }).catch((fail) => {            wx.showToast({                icon: 'error',                title: '请稍后再试',            });        });    },});

        3.canvas.js

                只展示大体框架,具体内容涉及隐私去掉了。

                wxml返回的是页面内容的字符串。

const wxml = ( name, avatarurl,title,teacher,qr_code ) => {    return `    <view class="poster-wapper">        <image class="poster-img" src="https://1.png"/>        <view class="author">            <text class="author-text">作者:${name}</text>        </view>        <view class="head">            <view class="head-border">                <image class="head-img" src="${avatarurl}"></image>            </view>        </view>                <view class="poster-info">            <view class="info">                <text class="title">挑战内容:《${title}》</text>                `+ (teacher?`<text class="teacher">老师:${teacher}</text>`:'')                +` <view class="line"></view>                    <text class="tip">本次朗读近乎完美!快来听听吧!</text>            </view>            <image class="qrcode-img" src="${qr_code}" />        </view>    </view>    `}const style = {    posterWapper:{        display: 'flex',        flexDirection: 'column',        alignItems: 'center',        justifyContent: 'center',        position: 'relative',    },        posterImg: {        width: 325,        height: 550    },    author: {        width: 119,        height: 32,        borderRadius: 12,        backgroundColor: 'rgba(255,255,255,0.8)',        position: 'absolute',        paddingLeft: 18,        top: 353,        left: 45,    },    authorText: {        width: 98,        height: 32,        paddingLeft: 13.5,        fontSize: 11,        fontWeight: 600,        color: '#333333',        verticalAlign: 'middle',    },        head: {        width: 51,        height: 51,        borderRadius: 25.5,        display: 'flex',        alignItems: 'center',        justifyContent: 'center',        position: 'absolute',        top: 343,        left: 12,        backgroundColor: 'rgba(255,255,255,0.8)',    },    headBorder: {        width: 46,        height: 46,        backgroundColor: 'rgba(255,255,255)',        borderRadius: 23,        display: 'flex',        alignItems: 'center',        justifyContent: 'center',    },    headImg: {        width: 43,        height: 43,        borderRadius: 20,    },    posterInfo:{        position: 'absolute',        bottom: -6,        width: 325,        height: 143,        backgroundColor: '#FFFFFF',        borderRadius: 10,        display: 'flex',        flexDirection: 'row'    },        info: {        width: 210,        height: 140,        display: 'flex',        flexDirection: 'column',        justifyContent: 'center',        paddingTop: 6,        paddingLeft: 15    },        title: {        width: 210,        height: 24,        fontSize: 13,        fontWeight: 600,        color: '#333333',        lineHeight: 24    },        teacher:{        width: 210,        height: 24,        fontSize: 13,        fontWeight: 400,        color: '#666666',        lineHeight: 24,    },    line:{        width: 190,        height: 1,        backgroundColor: 'rgba(3,0,0,0.16)'    },    tip: {        height: 24,        width: 210,        fontSize: 13,        fontFamily: 'PingFang SC',        fontWeight: 600,        color: '#333333',        lineHeight: 24,    },        btn:{        width: 140,        height: 33,        backgroundColor: '#FF6000',        borderRadius: 19,        lineHeight: 33,        textAlign: 'center',        marginTop: 7.5,        position: 'relative'    },    btnText:{        width: 140,        height: 33,        fontSize: 18,        fontFamily: 'PingFang SC',        fontWeight: 600,        color: '#FFFFFF',    },    btnImg:{        width:37,        height:18,        position: 'absolute',        left: 150,        top: 9    },        qrcodeImg:{        width: 92,        height: 92,        marginLeft: 5,        position: 'absolute',        bottom: 33,        right: 12    }}module.exports = {    wxml,    style}  

注意点⚠️:

        1.wxml支持 viewtextimage 三种标签,通过 class 匹配 style 对象中的样式。

        2.css对象属性值为对应 wxml 标签的 class 驼峰形式。需为每个元素指定 width 和 height 属性,否则会导致布局错误。

        3.存在多个 className 时,位置靠后的优先级更高,子元素会继承父级元素的可继承属性。

元素均为 flex 布局。left/top 等 仅在 absolute 定位下生效。

        4.css不支持背景图片,在wxml中用img代替。

        5.在写text标签时外边必须套一层view标签,否则不显示。(这一点是我遇到的问题,不知道是不是这样规定)

补充:(2022/12/15)

背景图片在开发工具和开发版都可以正常显示,但是在体验版显示不出来;

图片的域名在项目配置里没有,在后台管理-开发设置-服务器域名-request合法域名-配置图片的域名即可正常显示。


点击全文阅读


本文链接:http://zhangshiyu.com/post/58497.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1