更新记录
1.0.0(2022-06-28)
下载此版本
版本1
平台兼容性
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 里三种类型组件的
type
为box
、img
、text
<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 容器
{
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 |
省略字符 配合maxBoxWidht 和maxLine |
string |
... |
Ime 图片
- 通过
src
属性填写图片路径。
- 图片路径支持:网络图片,本地图片,database64
- 支持
css
的 object-fit
属性
- 支持
css
的 object-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>