更新记录

1.0.0(2022-06-28)

版本1


平台兼容性

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

diy-canvas 画板

uniapp 海报、签名画板

平台兼容

v2 v3 H5 微信小程序 App PC
未测 win(√) safari(未测)

因本人主要涉及到这几方面,其他家小程序没有涉猎😀😀😀😀😀

安装

在市场导入diy-canvas uni_modules版本的即可

代码演示

完整代码,props说明。见最下方

基本用法

  • 插件提供 JSON 和 自定义 的方式绘制海报 两者可配合使用
  • 插件提供 在canvas上签名

方式一 JSON

  • 在 json 里三种类型组件的typeboximgtext
        <diy-canvas 
            ref='diyCanvas' 
            cBackgroundColor='#F0BF4C' 
            :defaultW='defaultW' 
            :canvasHeight='canvasHeight' 
            :dataList='dataArr' 
            @success='success'>
        </diy-canvas>
        data() {
            return {
                isDiyRender: true,
                signatureStyle:{
                    color:'red',
                    size:6
                },
                path: '',
                shareImg: "",
                defaultW: 750, //设计图 宽 默认750px 下面数据结构中的大小(width,height)位置(left,top)要和设计图一毛一样不然会和设计图有差距 所有元素定位都是absolute
                canvasHeight: 'auto', //canvas 高度 默认auto 自动适配高度   如果小于要绘画数据的高度 图片则会显示不全
                dataArr: [{
                        type: 'box',
                        left: 32,
                        top: 28,
                        width: 686,
                        height: 794,
                        borderRadius: '20px',
                        borderColor: 'red',
                        backgroundColor: 'black',
                        lineWidth: 12,
                    },
                    {
                        type: 'img',
                        left: 56,
                        top: 60,
                        src: 'https://img.alicdn.com/imgextra/i3/O1CN01Sf6dER1zbJ3uVQ0lE_!!6000000006732-0-tps-846-472.jpg', //有的网络图片开发工具可以,真机不行。还有就是跨域图片不行
                        // src: require('@/static/c.jpg'),//或者 require('../../static/c.jpg')
                        // src: require('./a.png'),//注意 同目录下一定要加 ./,  或者 pages/index/a.png
                        // src: require('pages/index/a.png'),//注意 同目录下一定要加 ./,  或者 pages/index/a.png 
                        width: 140,
                        height: 140,
                        objectFit: 'none',
                        borderRadius: '20px 30px 40px 50px / 50px 60px 70px 80px',
                        borderColor: 'red',
                        lineWidth: 4,
                    },
                    {
                        type: 'text',
                        left: 224,
                        top: 60,
                        text: "发到付围绕大噶啊手动发到付围绕大噶啊手动",
                        font: '32px Fira Sans',
                        color: 'red',
                        maxBoxWidht: 200, //文字最长行宽
                        align: "center", //文字在盒子中的对齐方式 默认 left
                        autoLineBreak: true, //是否自动换行 默认 false
                        maxLine: 2, //最多显示行数
                        linHeight: 40, //行高
                        clampHint: '...', //省略字符
                    },
                    {
                        type: 'img',
                        left: 94,
                        top: 232,
                        src: require('../../static/c.jpg'),
                        // src: 'https://img.alicdn.com/imgextra/i3/O1CN01Sf6dER1zbJ3uVQ0lE_!!6000000006732-0-tps-846-472.jpg', //有的网络图片开发工具可以,真机不行。还有就是跨域图片不行
                        width: 562,
                        height: 562,
                        objectFit: 'none',
                        objectOsition: ['5px', '10%'],
                        borderRadius: '20px',
                        borderColor: 'blue',
                        lineWidth: 12,

                    },
                ],
            };
        },

方式二 自定义

        <diy-canvas 
            ref='diyCanvas' 
            cBackgroundColor='#F0BF4C' 
            :isDiyRender='isDiyRender'
            :defaultW='defaultW' 
            :canvasHeight='canvasHeight' 
            :dataList='dataArr' 
            :diyRender="diyRender" 
            @success='success'>
        </diy-canvas>
            methods:{
                diyRender() {
                //本来准备打算内部用正则来搞一下 有点麻烦 还未实现 暂时就先这样 涉及到元素大小,位置的数值就先 *rpx
                return function str(rpx) {
                    this.ctx.beginPath();
                    this.ctx.lineWidth = 12 * rpx; //设置线宽状态
                    this.ctx.strokeStyle = 'red'; //设置线的颜色状态
                    this.ctx.lineCap = 'round'
                    this.ctx.lineJoin = 'round'
                    this.ctx.moveTo(32 * rpx, 28 * rpx);
                    this.ctx.lineTo(718 * rpx, 822 * rpx);
                    this.ctx.stroke();

                    this.ctx.beginPath();
                    this.ctx.lineWidth = 1; //设置线宽状态
                    this.ctx.strokeStyle = 'black'; //设置线的颜色状态
                    this.ctx.fillStyle = "red";
                    this.ctx.arc(660 * rpx, 535 * rpx, 20 * rpx, 0 * rpx, 2 * Math.PI);
                    this.ctx.fill();
                    this.ctx.stroke();

                    this.ctx.beginPath();
                    this.ctx.lineWidth = 1; //设置线宽状态
                    this.ctx.strokeStyle = 'black'; //设置线的颜色状态
                    this.ctx.fillStyle = "red";
                    this.ctx.arc(90 * rpx, 535 * rpx, 20 * rpx, 0 * rpx, 2 * Math.PI);
                    this.ctx.fill();
                    this.ctx.stroke();

                    this.ctx.textBaseline = "top";
                    this.ctx.textAlign = 'left';
                    this.ctx.globalAlpha = 1;
                    this.ctx.font = `${24*rpx}px  Fira Sans`;
                    this.ctx.fillStyle = 'red'; //文字颜色:默认黑色
                    this.ctx.fillText('技术部', 224 * rpx, 160 * rpx) //绘制文本

                }
            },
}

canvas签名

        <diy-canvas 
            ref='diyCanvas' 
            cBackgroundColor='#F0BF4C' 
            :isSignature='true'
            navigationBarHeight='44'
            :signatureStyle="signatureStyle"
            :showCWidth='300'
            :isDiyRender='isDiyRender'
            :defaultW='defaultW' 
            :canvasHeight='canvasHeight' 
            :dataList='dataArr' 
            :diyRender="diyRender" 
            @success='success'>
        </diy-canvas>

Box 容器

  • 类似于 view、div
{
    type: 'box',
    left: 32,
    top: 28,
    width: 686,
    height: 794,
    borderRadius: '20px',
    borderColor: 'red',
    backgroundColor: 'black',
    lineWidth: 12,
}
参数 说明 类型 默认值
left 距离canvas左边距离 number 0
top 距离canvas顶部距离 number 0
width box宽度 number 0
height box高度 number 0
borderRadius css属性border-radius string 0
borderColor 边框颜色 string #ffffff
backgroundColor box背景颜色 string #ffffff
lineWidth 边框宽度 number 1px

Text 文本

  • 通过 text 属性填写文本内容。
    {
    type: 'text',
    left: 224,
    top: 60,
    text: "发到付围绕大噶啊手动发到付围绕大噶啊手动",
    font: '32px Fira Sans',
    color: 'red',
    maxBoxWidht: 200, //文字最长行宽
    align: "center", //文字在盒子中的对齐方式 默认 left
    autoLineBreak: true, //是否自动换行 默认 false
    maxLine: 2, //最多显示行数
    linHeight: 40, //行高
    clampHint: '...', //省略字符
    }
    参数 说明 类型 默认值
    left 距离canvas左边距离 number 0
    top 距离canvas顶部距离 number 0
    text 文本内容 string -
    font canvas.font string -
    borderRadius css属性border-radius string 0
    color 字体颜色 string black
    maxBoxWidht 文字最长行宽 string -
    align 文字在盒子中的对齐方式 配合maxBoxWidht ['left','center','right'] number left
    autoLineBreak 是否自动换行 配合maxBoxWidht boolean false
    maxLine 最多显示行数 配合maxBoxWidht number 1
    linHeight 行高 number -
    clampHint 省略字符 配合maxBoxWidhtmaxLine string ...

Ime 图片

  • 通过 src 属性填写图片路径。
  • 图片路径支持:网络图片,本地图片,database64
  • 支持 cssobject-fit属性
  • 支持 cssobject-position属性
  • 什么跨域,安全域名问题,自己注意
    {
    type: 'img',
    left: 56,
    top: 60,
    // src: 'https://...',//有的网络图片开发工具可以,真机不行。还有就是跨域图片不行
    // src:'data:image/png;base64,iVBO......',//可使用dataBase64格式
    // src: require('@/static/c.jpg'),//或者 require('../../static/c.jpg')
    // src: require('./a.png'),//注意 同目录下一定要加 ./,  或者 pages/index/a.png
    src: require('pages/index/a.png'),//注意 同目录下一定要加 ./,  或者 pages/index/a.png
    width: 140,
    height: 140,
    objectFit: 'fill',
    objectOsition: ['5px', '10%'],
    borderRadius: '20px 30px 40px 50px / 50px 60px 70px 80px',
    borderColor: 'red',
    lineWidth: 4,
                    }
    参数 说明 类型 默认值
    left 距离canvas左边距离 number 0
    top 距离canvas顶部距离 number 0
    src 图片内容 string -
    objectFit css属性object-fit string -
    objectOsition css属性object-position string -
    borderRadius css属性border-radius string 0
    width 图片宽度 number 0
    height 图片高度 number 0
    borderRadius css属性border-radius string 0
    borderColor 边框颜色 string #ffffff
    backgroundColor 背景颜色 string #ffffff
    lineWidth 边框宽度 number 1px

API

Props

        <diy-canvas 
            ref='diyCanvas' 
            cBackgroundColor='#F0BF4C' 
            :isSignature='true'
            navigationBarHeight='44'
            :signatureStyle="signatureStyle"
            :showCWidth='300'
            :isDiyRender='isDiyRender'
            :defaultW='defaultW' 
            :canvasHeight='canvasHeight' 
            :dataList='dataArr' 
            :diyRender="diyRender" 
            @success='success'>
        </diy-canvas>
参数 说明 类型 默认值
cBackgroundColor 画布填充颜色 string #ffffff
defaultW 设计图 宽 默认750px 下面数据结构中的大小(width,height)位置(left,top)等要和设计图一毛一样,不然会和设计图有差距 所有元素定位都是absolute number 750
canvasHeight canvas 高度 默认auto 自动适配高度 如果小于要绘画数据的高度 图片则会显示不全 string auto
dataList 绘画数据json array []
isSignature 是否要展示canvas(可以在上面签名) boolean -
signatureStyle 画笔颜色,大小自定义 object {color:'red',size:2}
showCWidth 显示在页面上canvas的宽 (值越小生成的图片越模糊,pc端尤为明显,自己尝试) number 屏幕宽度
navigationBarHeight 用于pc端签名时 number 44 uniapp默认顶部导航栏高度
isDiyRender true : 执行自定义渲染 diyRender false:不执行 渲染顺序 dataList -> diyRender boolean true
diyRender 自定义绘画 参考完整代码 function -

事件 Events

事件名 说明 返回值
success 生成图片成功 path

内部函数 Ref

事件名 说明 返回值
onSavePoster 保存图至本地 -
quash 撤销上一次签名 -
clearCanvas 只把内容清空 canvas 宽度和高度都不变 cBackgroundColor 还存在 -
saveImg canvas保存为图片 -

完整代码

<template>
    <view class="namecard">
        <view class="btn"  style="line-height: 40px;border: 1px solid black;" @click="quash">撤销</view>
        <view @click="aa" style="line-height: 40px;border: 1px solid black;">清空画布所有</view>
        <view @click="bb"  style="line-height: 40px;border: 1px solid black;">是否显示画布</view>
        <view @click="saveImg"  style="line-height: 40px;border: 1px solid black;">canvas转图片</view>
        <image :src="shareImg"  style="line-height: 40px;border: 1px solid black;" mode="widthFix" @click="dowload"></image>

        <diy-canvas 
            ref='diyCanvas' 
            cBackgroundColor='#F0BF4C' 
            :isSignature='isSignature'
            navigationBarHeight='44'
            :signatureStyle="signatureStyle"
            showCWidth="sdfg"
            :isDiyRender='isDiyRender'
            :defaultW='defaultW' 
            :canvasHeight='canvasHeight' 
            :dataList='dataArr' 
            :currentWebview='currentWebview'
            :diyRender="diyRender" 
            @success='success'>
        </diy-canvas>

    </view>
</template>

<script>
    export default {
        data() {
            return {
                isSignature:true,
                isDiyRender: true,
                showCWidth:200,
                signatureStyle:{
                    color:'red',
                    size:6
                },
                path: '',
                shareImg: "",
                defaultW: 750, //设计图 宽 默认750px 下面数据结构中的大小(width,height)位置(left,top)要和设计图一毛一样不然会和设计图有差距 所有元素定位都是absolute
                canvasHeight: 'auto', //canvas 高度 默认auto 自动适配高度   如果小于要绘画数据的高度 图片则会显示不全
                dataArr: [{
                        type: 'box',
                        left: 32,
                        top: 28,
                        width: 686,
                        height: 794,
                        borderRadius: `${20}px`,
                        borderColor: 'red',
                        backgroundColor: 'black',
                        lineWidth: 12,
                    },
                    {
                        type: 'img',
                        left: 56,
                        top: 60,
                        src: 'https://img.alicdn.com/imgextra/i3/O1CN01Sf6dER1zbJ3uVQ0lE_!!6000000006732-0-tps-846-472.jpg', //有的网络图片开发工具可以,真机不行。还有就是跨域图片不行
                        // src: require('@/static/c.jpg'),//或者 require('../../static/c.jpg')
                        // src: require('./a.png'),//注意 同目录下一定要加 ./,  或者 pages/index/a.png
                        // src: require('pages/index/a.png'),//注意 同目录下一定要加 ./,  或者 pages/index/a.png 

                        width: 140,
                        height: 140,
                        objectFit: 'none',
                        borderRadius: `${20}px ${30}px ${40}px ${50}px / ${50}px ${60}px ${70}px ${80}px`,
                        borderColor: 'red',
                        lineWidth: 4,
                    },
                    {
                        type: 'text',
                        left: 224,
                        top: 60,
                        text: "发到付围绕大噶啊手动发到付围绕大噶啊手动",
                        font: `${32}px Fira Sans`,
                        color: 'white',
                        maxBoxWidht: 200, //文字最长行宽
                        align: "center", //文字在盒子中的对齐方式 默认 left
                        autoLineBreak: true, //是否自动换行 默认 false
                        maxLine: 2, //最多显示行数
                        linHeight: 40, //行高
                        clampHint: '...', //省略字符
                    },
                    {
                        type: 'img',
                        left: 94,
                        top: 232,
                        src: require('../../static/c.jpg'),
                        width: 562,
                        height: 562,
                        objectFit: 'none',
                        objectOsition: [`${5}px`, '10%'],
                        borderRadius: `${20}px`,
                        borderColor: 'blue',
                        lineWidth: 12,

                    },
                ],
                currentWebview: '',
            };
        },
        onLoad() {
            //#ifdef APP-PLUS
            this.currentWebview = this.$scope.$getAppWebview()
            //#endif
        },
        mounted() {

            // setTimeout(() => {
            //  this.isDiyRender = true //true : 执行自定义渲染 appDiyRender和diyRender   false:不执行
            //  this.dataArr = [{
            //          type: 'box',
            //          left: 32,
            //          top: 28,
            //          width: 686,
            //          height: 794,
            //          borderRadius: '20px',
            //          borderColor: 'red',
            //          // backgroundColor: 'blue',
            //          lineWidth: 22,
            //      },
            //      {
            //          type: 'img',
            //          left: 56,
            //          top: 60,
            //          src: require('../../static/x.jpg'),
            //          width: 140,
            //          height: 140,
            //          objectFit: 'fill',
            //          borderRadius: '50%',
            //          borderColor: 'red',
            //          lineWidth: 12
            //      },
            //      {
            //          type: 'text',
            //          left: 224,
            //          top: 60,
            //          text: "4645654687978951dxfzdxcvgzd",
            //          font: '32px Fira Sans',
            //          color: 'red',
            //          maxBoxWidht: 200, //文字最长行宽
            //          align: "center", //文字在盒子中的对齐方式 默认 left
            //          autoLineBreak: true, //是否自动换行 默认 false
            //          maxLine: 2, //最多显示行数
            //          linHeight: 40, //行高
            //          clampHint: '...', //省略字符
            //      },
            //      {
            //          type: 'img',
            //          left: 94,
            //          top: 232,
            //          src: require('../../static/s.jpg'),
            //          width: 562,
            //          height: 562,
            //          objectFit: 'contain',
            //          objectOsition: ['0%', '0%'],
            //          borderRadius: '20px',
            //          borderColor: 'red',
            //          lineWidth: 12,

            //      },
            //  ]
            // }, 50000)
        },
        methods: {
            saveImg(){
                this.$refs.diyCanvas.saveImg()
            },
            quash(){
                this.$refs.diyCanvas.quash()
            },
            bb(){
                console.log(1111)
                this.isSignature=!this.isSignature
            },
            aa() { 
                this.$refs.diyCanvas.clearCanvas() //只把内容清空 canvas 宽度和高度都不变 cBackgroundColor 还存在 
                this.isDiyRender = true
                //注意 如果dataArr和上次相同(微信小程序 监听不到)页面就只有第一次会把box画出来
                //#ifdef MP-WEIXIN
                this.dataArr = []
                //#endif
                setTimeout(()=>{
                    this.dataArr = [{
                        type: 'box',
                        left: 32,
                        top: 28,
                        width: 686,
                        height: 794,
                        borderRadius: '20px',
                        borderColor: 'red',
                        backgroundColor: 'blue',
                        lineWidth: 22,
                    }]
                },40)

            },
            success(e) {
                this.shareImg = e
            },
            diyRender() {
                //本来准备打算内部用正则来搞一下 还未实现 暂时就先这样 涉及到元素大小,位置的数值就先 *rpx
                return function str(rpx) {
                    this.ctx.beginPath();
                    this.ctx.lineWidth = 12 * rpx; //设置线宽状态
                    this.ctx.strokeStyle = 'red'; //设置线的颜色状态
                    this.ctx.lineCap = 'round'
                    this.ctx.lineJoin = 'round'
                    this.ctx.moveTo(32 * rpx, 28 * rpx);
                    this.ctx.lineTo(718 * rpx, 822 * rpx);
                    this.ctx.stroke();

                    this.ctx.beginPath();
                    this.ctx.lineWidth = 1; //设置线宽状态
                    this.ctx.strokeStyle = 'black'; //设置线的颜色状态
                    this.ctx.fillStyle = "red";
                    this.ctx.arc(660 * rpx, 535 * rpx, 20 * rpx, 0 * rpx, 2 * Math.PI);
                    this.ctx.fill();
                    this.ctx.stroke();

                    this.ctx.beginPath();
                    this.ctx.lineWidth = 1; //设置线宽状态
                    this.ctx.strokeStyle = 'black'; //设置线的颜色状态
                    this.ctx.fillStyle = "red";
                    this.ctx.arc(90 * rpx, 535 * rpx, 20 * rpx, 0 * rpx, 2 * Math.PI);
                    this.ctx.fill();
                    this.ctx.stroke();

                    this.ctx.textBaseline = "top";
                    this.ctx.textAlign = 'left';
                    this.ctx.globalAlpha = 1;
                    this.ctx.font = `${24*rpx}px  Fira Sans`;
                    this.ctx.fillStyle = 'white'; //文字颜色:默认黑色
                    this.ctx.fillText('技术部', 224 * rpx, 160 * rpx) //绘制文本

                }
            },
            dowload() {
                this.$refs.diyCanvas.onSavePoster()
            }
        }
    }
</script>

<style lang="scss" scoped>
    .namecard {}
</style>

隐私、权限声明

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

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

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

许可协议

MIT协议

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