uniapp实现微信小程序的电子签名效果(附demo)

作者:瓜子三百克 时间:2024-04-19 09:55:39 

画布可以做很多事情,比如可以绘图,也可以做海报。在这里只是想拿它来的实现亲笔签名,开启不一样的亲笔签名姿势。

开发框架:uniapp
开发语言:vue2
展示平台:微信小程序(实际可以兼容多个平台)

标签和样式没什么好说的,这里绘制了简单的页面,见下图:

uniapp实现微信小程序的电子签名效果(附demo)

1、标签和样式

<template>
<view class="page-content">
<view class="form">
<view class="form-content">
<canvas class="form-content__canvas" canvas-id="canvas_sign" @touchstart="touchstart"
@touchmove="touchmove" @touchend="touchend" disable-scroll="true"></canvas>
</view>

<view class="form-footer">
<button class="form-footer__reset" @click="autographClick(1)">重置</button>
<button class="form-footer__save" @click="autographClick(2)">保存</button>
<button class="form-footer__preview" @click="autographClick(3)">预览</button>
</view>
</view>

</view>
</template>

<style lang="scss" scoped>
/*
* 横屏后的适配方案
* @param $rpx为需要转换的字号
* @参考 https://blog.csdn.net/sdfsfsdscd/article/details/91375066
**/
@function tovmin($rpx) {
@return #{$rpx * 100 / 750}vmin;
}

.page-content {
width: 100vw;
height: 100vh;

.form {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;

.form-content {
width: 100%;
height: 100%;

&__canvas {
height: calc(100vh - tovmin(20) - tovmin(120) - constant(safe-area-inset-bottom));
height: calc(100vh - tovmin(20) - tovmin(120) - env(safe-area-inset-bottom));
width: 100vw;
}
}

.form-footer {
padding-top: tovmin(20);
height: calc(tovmin(120) + constant(safe-area-inset-bottom));
height: calc(tovmin(120) + env(safe-area-inset-bottom));
width: 100%;

display: flex;
flex-direction: row;

background: #FFFFFF;
box-shadow: 0 tovmin(4) tovmin(20) tovmin(2) rgba(183, 183, 183, 0.20);

button {
width: 20vw;

height: tovmin(88);
line-height: tovmin(88);
border-radius: tovmin(48);
text-align: center;
font-size: tovmin(36);
font-weight: bold;
}

button::after {
border: none;
}

&__reset {
color: #008AFE;
border: tovmin(1) solid #008AFE;
}

&__save {
background-image: linear-gradient(135deg, #1BC5FF 0%, #008AFE 100%);
}

&__preview {
color: #008AFE;
border: tovmin(1) solid #008AFE;
}
}
}
}
</style>

2、横屏切换

到【pages.json】文件中添加横屏切换配置
注意:不同的平台横屏切换将有所不一样。这里是针对微信小程序的横屏适配

{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "亲笔签名",//导航栏标题
"pageOrientation": "landscape",//切换横屏
"enablePullDownRefresh": false,//关闭下拉刷新
"disableScroll": true // 整体页面禁止上下滑动
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#f5f5f5",
"navigationStyle": "default", // default/custom。custom即取消默认的原生导航栏
"mp-alipay": {
"transparentTitle": "always",
"titlePenetrate": "YES"
}
}
}

然后是绘制逻辑处理,注意点在代码中备注:

3、绘图

3.1、初始化数据会吧?

data() {
return {
canvasCtx: '', //绘图图像
points: [], //路径点集合
hasSign: false,
isInit: false,
}
},
onLoad(query) {
this.canvasCtx = uni.createCanvasContext('canvas_sign', this) //创建绘图对象
//设置画笔样式
this.canvasCtx.lineWidth = 6
// 设置线条的端点样式
this.canvasCtx.lineCap = 'round'
// 设置线条的交点样式
this.canvasCtx.lineJoin = 'round'
},

3.2、触摸开始时获取起点,会吧?

touchstart: function(e) {
if (!this.isInit) {
this.isInit = true
this.autographClick(1);
}
let startX = e.changedTouches[0].x
let startY = e.changedTouches[0].y
let startPoint = {
X: startX,
Y: startY
}
this.points.push(startPoint)
//每次触摸开始,开启新的路径
this.canvasCtx.beginPath()
},

3.3、触摸移动获取路径点,会吧?

touchmove: function(e) {
let moveX = e.changedTouches[0].x
let moveY = e.changedTouches[0].y
let movePoint = {
X: moveX,
Y: moveY
}
this.points.push(movePoint) //存点
let len = this.points.length
if (len >= 2) {
this.draw() //绘制路径
}

},

3.4、触摸结束,将未绘制的点清空防止对后续路径产生干扰,简单吧?

touchend: function() {
this.points = []
this.canvasCtx.draw(true)
},

3.5、绘制笔迹,没得问题吧?

这里有几个注意点:

1.为保证笔迹实时显示,必须在移动的同时绘制笔迹
2.为保证笔迹连续,每次从路径集合中区两个点作为起点(moveTo)和终点(lineTo)
3.将上一次的终点作为下一次绘制的起点(即清除第一个点)

draw: function() {
let point1 = this.points[0]
let point2 = this.points[1]
this.points.shift()
this.canvasCtx.moveTo(point1.X, point1.Y)
this.canvasCtx.lineTo(point2.X, point2.Y)
this.canvasCtx.stroke()
this.canvasCtx.draw(true)
this.hasSign = true
},

4、扫尾处理

上面的实现了,说明就可以签下你大名了。这里扫尾工作(按钮点击功能实现)只是景上添花。根据实际情况不一定要做。

<script>
export default {
methods: {
// 底部按钮点击操作
autographClick(type) {
let that = this
if (type === 1) {
//清空画布
this.hasSign = false
uni.getSystemInfo({
success: function(res) {
let canvas = uni.createSelectorQuery().select('.form-content__canvas')
canvas.boundingClientRect().exec(function(data) {
console.log('canvas', data)
console.log('canvas wh:' + data[0].width + 'X' + data[0].height)
let canvasw = Math.ceil(data[0].width)
let canvash = Math.ceil(data[0].height)
that.canvasCtx.fillStyle = '#fff'
that.canvasCtx.fillRect(0, 0, canvasw, canvash)
that.canvasCtx.draw(true)
})
}
})

} else {
if (!this.hasSign) {
uni.showToast({
title: '签名不能为空',
icon: 'none',
duration: 2000
})
return
}
uni.getSystemInfo({
success: function(res) {
let canvas = uni.createSelectorQuery().select('.form-content__canvas')
canvas.boundingClientRect().exec(function(data) {
console.log('canvas saveSign:', data[0].width + 'X' + data[0].height)
let canvasw = Math.ceil(data[0].width)
let canvash = Math.ceil(data[0].height)
uni.canvasToTempFilePath({
destWidth: canvasw,
destHeight: canvash,
fileType: 'jpg',
canvasId: 'canvas_sign',
success: function(res) {
console.log('图片导出成功:', res)
let path = res.tempFilePath

// 保存图片
if (type === 2) {
that.uploadPic(path)
} else if (type === 3) {
// 预览图片
uni.previewImage({
urls: [path]
})
}
},
fail: (err) => {
// http://tmp/2LVQyvzddk2R820a9009dff43323d8e7fc9ef7a8d076.jpg
console.log('图片导出失败:', err)
}
})
})
}
})
}
},

// 图片上传处理
uploadPic(tempFile) {
// 1、将本地图片上传到服务器(假装是七牛云服务器)
// 2、将七牛云返回的链接,上传到我们的服务器平台
console.log("------:", tempFile);
uni.showLoading({
title: '正在上传中...'
})
setTimeout(() => {
uni.showToast({
title: '假装签名上传成功',
duration: 2000,
icon: 'none'
});
}, 1000);
}
}
}
</script>

demo地址:

gitee地址:https://gitee.com/chenzm_186/autograph-mini.git

来源:https://blog.csdn.net/weixin_38633659/article/details/124700129

标签:uniapp,小程序,电子签名
0
投稿

猜你喜欢

  • MySQL错误TIMESTAMP column with CURRENT_TIMESTAMP的解决方法

    2024-01-25 20:47:47
  • 使用classList来实现两个按钮样式的切换方法

    2024-04-16 09:35:19
  • Selenium结合BeautifulSoup4编写简单的python爬虫

    2022-04-04 11:22:33
  • php输出xml必须header的解决方法

    2023-09-11 20:00:16
  • element-UI el-table树形数据 修改小三角图标方式

    2023-07-02 17:09:53
  • IE6局部调用PNG32合并图片

    2009-03-11 21:24:00
  • vue.js2.0 实现better-scroll的滚动效果实例详解

    2023-07-02 16:58:50
  • PYTHON 中使用 GLOBAL引发的一系列问题

    2023-07-08 16:24:21
  • Ubuntu 14.04+Django 1.7.1+Nginx+uwsgi部署教程

    2021-03-14 09:16:22
  • python使用Qt界面以及逻辑实现方法

    2023-10-23 23:28:09
  • 零基础写python爬虫之抓取百度贴吧并存储到本地txt文件改进版

    2022-12-20 08:32:42
  • 编写python代码实现简单抽奖器

    2023-04-07 12:32:48
  • 使用Python的音乐播放器GUI的实现

    2022-03-02 05:02:45
  • asp如何实时获知多少人在线?

    2010-05-18 18:34:00
  • php购物车实现方法

    2023-11-16 22:54:51
  • 使用Python将语音转换为文本的方法

    2022-10-16 07:48:06
  • MySQL数据备份方法的选择与思考

    2024-01-19 21:02:50
  • Python实现快速傅里叶变换的方法(FFT)

    2022-09-18 07:21:47
  • pytorch使用horovod多gpu训练的实现

    2022-01-07 16:01:18
  • TensorFlow实现RNN循环神经网络

    2023-03-18 18:12:49
  • asp之家 网络编程 m.aspxhome.com