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

news2024/11/20 22:40:20

一、需求

        项目中要实现一个将图片分享到朋友圈的功能,将生成的海报转成图片保存到手机。用到了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');
//自己封装的微信api
import 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://www.coloradmin.cn/o/408777.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多款顶级好用的 Vue 表单设计器测评推荐,可拖拽生成表单

本文完整版&#xff1a;《多款顶级好用的 Vue 表单设计器测评推荐&#xff0c;可拖拽生成表单》 Vue 表单设计器form-generator - 适配 Element Plus UI 框架的表单设计器form-render - 阿里团队开源表单设计器&#xff0c;自家 Antd UI 框架友好form-create - 支持Vue3 及 Ele…

内网npm私有仓库搭建以及使用教程

前言 前端团队沉淀一套通用的UI库、工具类、脚手架&#xff0c;不允许在公网发布&#xff0c;内网npm私有库搭建需求应运而生。如何在内网环境搭建npm私有仓库并使用&#xff1f;主角登场了 —— Verdaccio。接下来我来教大家使用 verdaccio 在内网环境中搭建npm私有仓库。 基…

canvas详细入门教程(1W字 吐血分享)

大家好&#xff0c;我是潘潘 今天为大家带来的是我已经写了很久了的canvas详细教程&#xff0c;对入门canvas很有帮助。 点击跳转原文&#xff1a; canvas详细教程原文 canvas是什么&#xff1f; 简单来说&#xff0c;<canvas> 是HTML5中的标签&#xff0c;它是一个容…

20分钟学会flex布局,熊二都表示学会了,你呢?

✏️ 作者&#xff1a;大二计算机专业学生 ♉ 星座&#xff1a;金牛座 &#x1f3e0; 主页&#xff1a;查看更多文章 &#x1f3c2; 关键&#xff1a;flex 前端布局 熊二都会 大家好&#xff0c;我是小周&#xff0c;今天分享的是熊二都能学会的前端 flex 布局&#xff0c;篇幅…

小程序 getActivePinia was called with no active Pinia. Did you forget to install pinia?

小程序项目使用pinia做状态管理报错&#xff1a; Error: [&#x1f34d;]: getActivePinia was called with no active Pinia. Did you forget to install pinia? const pinia createPinia() app.use(pinia) app运行打包时有个同样的错误 错误原因是&#xff1a;在外部js/t…

Collections类详解

目录 一.Collections概述&#xff1a; 1.1什么是Collections类&#xff1a; 1.2 Collections类和collection的区别和联系&#xff1a; 二. Collections类的主要方法&#xff1a; 一.Collections概述&#xff1a; 1.1 什么是Collections类&#xff1a; Java.util.Collections…

【Node.js】Express框架的基本使用

✍️ 作者简介: 前端新手学习中。 &#x1f482; 作者主页: 作者主页查看更多前端教学 &#x1f393; 专栏分享&#xff1a;css重难点教学 Node.js教学 从头开始学习 目录 初识Express Express简介 什么是Express 进一步理解 Express Express能做什么 Express的基本使用 …

前端登录退出:处理Token问题(获取、缓存、失效处理)以及代码实现

目录一、什么是Token二、获取token三、Token失效处理注意点1、主动退出2、Token过期① 逻辑图②方案③代码实现3、被人顶号① 逻辑图② 方案③代码实现一、什么是Token Token是服务端生成的一串字符串&#xff0c;当用户第一次登陆成功后&#xff0c;服务器会生成一个token&am…

vue 实现自适应屏幕

1.安装自适应屏幕插件&#xff08;优先使用vscode安装&#xff0c;需要调整px转化rem比例&#xff09; &#xff08;1&#xff09;安装插件&#xff1a; npm i lib-flexible --save &#xff08;2&#xff09;mian.js引入&#xff1a; import lib-flexible/flexible.js 2. 如果…

java中controller层是干嘛的?

最近在研究开源框架的源码&#xff0c;打算改写开源框架&#xff0c;适用于自身的业务场景。于是找到了一个框架(spiderFlow)。 根据他的git上的教程&#xff0c;搭建了一个。 controller层&#xff0c;在我们写代码的时候&#xff0c;一般为接口层&#xff0c;与前端&#xf…

CSS锥形渐变实现环形进度条

10月份因为疫情原因、又开启了居家办公模式&#xff0c;空闲之余&#xff0c;与其选择“躺平”&#xff0c;不如去做一些有意义的事情&#xff0c;内心的想法驱使着我去做些什么&#xff0c;但是又没有合适的素材&#xff0c;直到接手了最近的一个可视化项目&#xff0c;一个图…

若依框架---权限管理设计

前言 若依权限管理包含两个部分&#xff1a;菜单权限 和 数据权限。菜单权限控制着我们可以执行哪些操作。数据权限控制着我们可以看到哪些数据。 菜单是一个概括性名称&#xff0c;可以细分为目录、菜单和按钮&#xff0c;以若依自身为例&#xff1a; 目录&#xff0c;就是页…

关于古老的jsp页面的知识汇总(超详细)

1. 为什么要开发出来jsp文件呢&#xff1f; 面对需要将大量的结果&#xff0c;甚至是一整个<html>页面返回给响应体&#xff0c;之前的方法就显得十分麻烦。 之前我们是这样将结果返回给响应体的&#xff0c;如下图&#xff1a; 于是就设计了jsp文件&#xff0c;用来解决…

antd upload上传格式.doc、.docx、.pdf、.png、.jpg、.rar和大小100兆限制

限制上传文件格式.rar、.zip、.pdf、.jpg、.png、.docx antd 中upload对于限制上传文件格式的属性是accept&#xff0c;在开发的过程中&#xff0c;accept对于.doc、.docx、.pdf、.png、.jpg、.rar&#xff0c;格式的限制是完全没有问题的。但是测试和我说&#xff0c;当选择文…

前端开发之vue-grid-layout的使用和实例

前端开发之vue-grid-layout的使用和实例前言效果图一、vue中简单案例1、安装组件NPMYarn2、vue文件二、vue3使用&#xff08;vue文件&#xff09;1、需要导入vue3支持的该版本插件2、在mian.js里引入&#xff1a;三、在IE上无法打开&#xff0c;并报错缺少&#xff1a;&#xf…

【TypeScript基础】TypeScript之常用类型(下)

前言 博主主页&#x1f449;&#x1f3fb;蜡笔雏田学代码 专栏链接&#x1f449;&#x1f3fb;【TypeScript专栏】 上篇文章讲解了TypeScript的一些常用类型&#xff0c;&#x1f449;&#x1f3fb;详细内容请阅读【TypeScript基础】TypeScript之常用类型&#xff08;上&#x…

解决TypeError: Cannot read properties of undefined (reading ‘NormalModule‘)的三种方案

目录 前言 第一种 第二种 第三种 前言 大家好呀&#xff01;我是爷爷的茶七里香&#xff0c;今天遇到了一件&#x1f95a;疼的事&#xff0c;一个vuevant写的APP&#xff0c;更换了电脑之后运行不起来&#xff0c;就很奇怪很离谱&#xff0c;报错信息如下&#xff1a; ER…

使用Iframe打印预览pdf,兼容谷歌火狐浏览器

功能场景&#xff1a; 点击页面的打印按钮&#xff0c;可以调用浏览器的打印功能&#xff0c;并预览打印pdf文件。解决火狐浏览器出现about:blank问题。 功能实现&#xff1a; 实现思路&#xff1a; 使用接口获取pdf文件的二进制流&#xff0c;响应类型为blob将拿到的二进制…

vite 本地运行首次进入页面加载慢问题

思考 vite的适用场景是什么&#xff1f; 由于我使用了tailwindcss插件 使用webpack 每次启动所有的项目的css样式都预先使用tailwindcss 转换成css 性能普通的电脑启动项目需要1分钟到2分钟。不过首次加载不会有什么多大的延迟&#xff0c;按需导入的页面加载也不会有多大的延…

博客项目- SSM 实现

文章目录1. 创建项目2. 数据库设计3. 前置任务3.1 拦截器3.2 统一数据格式3.3 创建一个 Constant3.4 统一异常处理3.5 密码加密4. 功能实现4.1 登录功能4.2 注册功能4.3 博客列表页 &#xff08;功能实现&#xff09;4.3.1 左侧框4.3.2 右侧框 (分页功能 页面显示)4.4 博客详情…