更新记录

0.0.1(2023-11-16)

完成基本功能


平台兼容性

Vue2 Vue3
×
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
HBuilderX 3.8.11 × × × × ×
钉钉小程序 快手小程序 飞书小程序 京东小程序
× × × ×
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
× × × × × × × × ×

0.使用方法

下载zip包后解压,将文件夹内components文件夹复制到项目根目录,然后在任意页面直接引入即可

1.组件介绍

本组件用于将view界面中的text,image,view中的内容保存为图片

2.功能实现原理

本组件本质上是使用离屏canvas来绘制页面上的信息,实现过程如下:

(1)要获取界面中view,image,或text中的数据,可以通过uni.createSelectorQuery() API来获取需要绘制的信息,例如view的宽高,背景色。image的链接地址,绘制位置,大小尺寸等,下面使用说明会详细阐述

(2)将获取到的属性数据创建为一个数组,数组的格式在下面会详细说明。

(3)调用组件中的方法 drawCanvas(array)。组件即根据参数array数组中的数据,创建离屏canvas,并开始绘制。

(4)绘制完成后,可选择保存到本地,或发送给微信好友

3.使用示例

xml

<template>
    <view class="content">
        <tk-view2canvas ref="tkCanvas" 
             :canvas-width="canvasWidth" 
             :canvas-height="canvasHeight">
        </tk-view2canvas>
        <view class="queryInfo" data-type="view" data-bgcolor="#fff000"
              style="display: flex;flex-direction:column; width: 750rpx;height: 960rpx;justify-content: center;align-items: center;" >
            <image class="queryInfo" src="../../static/tp.jpg" style="width: 540rpx;height:960rpx;" 
            data-type="image" data-src="../../static/tp.jpg">
            </image>
            <text class="queryInfo" data-word="测试文本" data-size="50" data-color="#ff0000" data-type="text" 
            style="font-size: 50rpx;color: #ff0000;">
                测试文本
            </text>
        </view>
        <button @click="toCanvas">调用组件方法</button>
    </view>
</template>

script

<script>
    let arrayInfo = []
    export default {
        data() {
            return {
                canvasWidth: 1080,  //canvas的width
                canvasHeight: 1920, //canvas的height 我这里简单写成1080*1920.可以根据自己的业务需求去动态修改这个尺寸。
            }
        },
        onLoad() {

        },
        methods: {

            toCanvas(){
                let that = this
                arrayInfo = []
                // 1.先查询要绘制的view,image,text相关属性数据
                // 这里我将需要查询的所有view或text或image的类名都设置为queryInfo
                uni.createSelectorQuery().selectAll('.queryInfo').boundingClientRect().exec((res)=>{
                    console.log('获取到信息:',res[0])
                    let resArray = res[0]
                    for(let i=0;i<resArray.length;i++){
                        //1.判断查询到的组件类别,如果是view类,就按照view对应的格式将创建的对象添加到数组中
                        if(resArray[i].dataset.type == 'view'){
                            console.log('view')
                            let bgColor = resArray[i].dataset.bgcolor
                            let width = resArray[i].width
                            let height = resArray[i].height
                            let posX = resArray[i].left
                            let posY = resArray[i].top
                            arrayInfo.push({
                                type:'view',
                                width: width,
                                height: height,
                                bgColor: bgColor,
                                posX:posX,
                                posY:posY
                            })
                        }//2.判断查询到的组件类别,如果是image类,就按照image对应的格式将创建的对象添加到数组中
                        else if(resArray[i].dataset.type == 'image'){
                            console.log('image')
                            let type = 'image'
                            let src= resArray[i].dataset.src
                            let posX = resArray[i].left
                            let posY = resArray[i].top
                            let width = resArray[i].width
                            let height = resArray[i].height
                            arrayInfo.push({
                                type:'image',
                                src: src,
                                width:width,
                                height: height,
                                posX:posX,
                                posY:posY
                            })
                        }//3.判断查询到的组件类别,如果是text类,就按照text对应的格式将创建的对象添加到数组中
                        else if(resArray[i].dataset.type == 'text'){
                            console.log('text')
                            let type = 'text'
                            let color= resArray[i].dataset.color
                            let word= resArray[i].dataset.word
                            let size= resArray[i].dataset.size
                            let posX = resArray[i].left
                            let posY = resArray[i].top
                            arrayInfo.push({
                                type:'text',
                                color:color,
                                word:word,
                                size:size,
                                posX:posX,
                                posY:posY
                            })
                        }
                    }
                    //查询完毕后,也就创建好了arrayInfo数组,下面将arrayInfo数组作为参数,传给组件的drawCanvas()方法
                    that.$refs.tkCanvas.drawCanvas(arrayInfo)
                })

            },
        }
    }
</script>

4.代码说明

xml中

<tk-view2canvas ref="tkCanvas" :canvas-width="canvasWidth" :canvas-height="canvasHeight">

上面这段代码中, canvas-width,canvas-height,是本组件的两个props

分别代表了,要绘制图片的宽度,高度

定义 ref="tkCanvas" 是为了后面调用这个组件的方法。

<view class="queryInfo" data-type="view" data-bgcolor="#ffffff"
              style="display: flex;flex-direction:column; width: 750rpx;height: 960rpx;justify-content: center;align-items: center;" >
        <image class="queryInfo" src="../../static/tp.jpg" style="width: 540rpx;height:960rpx;" 
            data-type="image" data-src="../../static/tp.jpg">
        </image>
        <text class="queryInfo" data-word="测试文本" data-size="50" data-color="#ff0000" data-type="text" 
            style="font-size: 50rpx;color: #ff0000;">
                测试文本
        </text>
</view>

上面这段代码,是要绘制的view,image和text,绘制不同的标签,需要对应不同的属性数据。

script中

由于script中我通过uni.createSelectorQuery() API来获取标签中的数据,所以我在xml代码中使用 data- 的方式来确定需要查询的属性数据。在实际使用中,不一定要按照我的方式来确定属性数据。只需要确保最后传送给组件方法 drawCanvas()* 中的参数格式正确即可。

5.组件方法

drawCanvas(array)

这个方法是实现组件功能最核心的东西,这个参数就是一个数组,这里以下面的数组为例说明

let array = [
    {
        type: "view", 
        width: 390, 
        height: 499, 
        bgColor: "#fff000", 
        posX: 0, 
        posY:0
    },
    {
        type: "image", 
        src: "图片的网络地址或本地地址", 
        width: 280, 
        height: 464, 
        posX: 55,
        posY:55},
    {
        type: "text", 
        color: "#ff0000", 
        word: "测试文本", 
        size: 50, 
        posX: 143,
        posY: 150
    }]

这个数组中,有三个对象:

第一个对象的属性 type 为 view,表示要绘制的是一个view,width表示view的宽度,height表示view的高度,bgColor表示view的背景色,posX表示X轴的位置,posY表示Y轴位置。

第二个对象的属性type 为 image,表示要绘制的是一个image,src表示图片地址,可以是本地图片,也可以是网络图片,width表示图片的宽度,height表示图片的高度,posX表示X轴的位置,posY表示Y轴位置。

第三个对象的属性type 为text,表示要绘制的是一个text文本,color表示文本的颜色,word表示要绘制的字,size,表示文本的字号,posX表示文本的X轴位置,posY表示文本的Y轴位置。

因为canvas的原点(0,0),对应于屏幕的左上角,所以x轴坐标就等于 uni.createSelectorQuery() 查询后得到的标签 left 属性值。y轴坐标就等于uni.createSelectorQuery() 查询后得到的标签 top 属性值

注意:目前本组件只支持这3种type种的对应的这几个属性,数组种添加其他属性是无效的

6.绘制顺序

上面对参数array已经做了详细说明,组件绘制图片的顺序也是根据这个数组的顺序进行绘制,所以再给数组中添加数据是需要确定好需要绘制的顺序是什么。推荐的顺序,就是第一个数据作为整体的背景色或背景图片,然后再根据需要将要添加的图片或文字依次往下排列。

7.存在的BUG

canvas在绘制文字时,其字体、位置、大小可能会和预想的有些出入,应该是跟canvas本身绘图的机制有关。如果大家有比较好的解决方法,希望给我留言,我会尽快完善好

隐私、权限声明

1. 本插件需要申请的系统权限列表:

本地相册写入权限

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问