实现签名方法就是使用canvas

<canvas canvas-id="firstCanvas" id='firstCanvas' bindtouchstart="bindtouchstart" bindtouchmove="bindtouchmove"></canvas>

<!-- 旋装图片 -->
<canvas canvas-id="saveImg" id='saveImg'></canvas> <view class="clear" hidden="{{!sureBtn}}" bindtap='clear'>重新签名</view>
<view class="save {{sureBtn?'sureBet':''}}" bindtap='export'>完成</view>

在canvas上绑定手指点击事件和移动事件:

上图是想要实现的效果,

有几个考虑的点:

  • 1、签字区域和按钮都是横屏显示的,这个首先想到的使用微信小程序的方法直接在json文件设置"pageOrientation":"landscape",但效果是整个屏幕横屏,标题也横,效果不同。只能通过css方法旋转实现按钮横屏展示
  • 2、签字区域有个占位符,签字的时候需要去除,首先想到的是用个view去占位,然后点击切换为canvas,但是个人觉的略显刻意,就用canvas来旋转实现,bindtouchstart时让文字为空,这样也多了一个设置默认文字的函数
  • 3、生成图片,在使用wx.canvasToTempFilePath({})的时候发现生成的图片也是反着的,这里用了一个笨方法,添加一个canvas来单独处理图片旋转
//index.js
//获取应用实例
const app = getApp() Page({
data: {
context: null,
index: 0,
height: 0,
width: 0,
writeTips: '请清晰书写您的英文签名',
writeTipsTrue: true,
src:'',
sureBtn:false,
saveContext:null
},
/**记录开始点 */
bindtouchstart: function (e) {
let { writeTipsTrue } = this.data
if (writeTipsTrue) { this.data.context.clearRect(0, 0, this.data.width, this.data.height);
this.setData({ writeTipsTrue: false, sureBtn:true })
}
this.data.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y)
},
/**记录移动点,刷新绘制 */
bindtouchmove: function (e) {
this.data.context.setLineWidth(2) // 设置线条宽度
this.data.context.lineTo(e.changedTouches[0].x, e.changedTouches[0].y);
this.data.context.stroke();
this.data.context.draw(true);
this.data.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y);
}, /**清空画布 */
clear () {
let context = this.data.context
this.setData({ writeTipsTrue: true, sureBtn:false })
context.clearRect(0, 0, this.data.width, this.data.height);
// this.data.saveContext.clearRect(0, 0, this.data.height, this.data.width);
context.save();
context.setTransform(1, 0, 0, 1, Math.ceil(this.data.width / 2), 155); // 旋转画布 默认文字区域
context.rotate(Math.PI / 2);
let str = this.data.writeTips;
context.setFontSize(24)
context.setFillStyle('#ADADB2');
context.fillText(str, 0, 0)
context.restore();
context.draw()
},
/**导出图片 */
export () {
const that = this;
let signImg;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: that.data.width,
height: that.data.height,
destWidth: that.data.width,
destHeight: that.data.height,
canvasId: 'firstCanvas',
success (res) {
console.log(res.tempFilePath)
signImg = res.tempFilePath
that.setData({ src1: signImg})
//下载图片 wx.getImageInfo({
src: signImg, // 签字画布生成的暂存地址
success (res) {
// canvas绘制图片需要下载图片或者getImageInfo
console.log(res,'res'); let rototalImg = res.path
that.setData({ src: rototalImg})
if (rototalImg) {
// 单独处理图片旋转
that.saveImg(rototalImg) }
}
})
}
})
}, // drew img
saveImg (signImg){
if (!this.data.sureBtn){
app.toast(this, {
type: 'text',
text: '请清晰书写您的英文签名'
})
return }
// 旋转图
let that = this
const context = wx.createCanvasContext('saveImg');
this.setData({saveContext:context})
context.translate(that.data.width / 2, that.data.height / 2)
context.setTransform(1, 0, 0, 1, 0, Math.ceil(that.data.height / 2) -20);
context.rotate(-Math.PI / 2)
// context.drawImage(signImg, -that.data.width / 2, -that.data.height / 2, that.data.width, that.data.height)
context.drawImage(signImg, 0, 0, that.data.width, that.data.height) // context.fill()
//绘制图片 生成图片函数写在draw()的回调中,不然会出现还没有画图就生成图片的问题
context.draw(true,()=>{
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: that.data.height,
height: that.data.width,
destWidth: that.data.height,
destHeight: that.data.width,
canvasId: 'saveImg',
fileType: 'png',
success: function (res) {
var tempFilePath = res.tempFilePath;
console.log(tempFilePath);
that.setData({ src: tempFilePath })
// 生成图片 并返回上一页 赋值
let curPages = getCurrentPages();
var prevPage = curPages[curPages.length - 2]
prevPage.setData({
signImg: tempFilePath,
})
wx.navigateBack({
delta: 1
});
},
fail: function (res) {
console.log(res);
}
});
}) },
onLoad: function (options) { },
onShow: function () {
// 进入页面渲染canvas
let query = wx.createSelectorQuery();
const that = this;
let context
query.select('#firstCanvas').boundingClientRect();
query.exec(function (rect) {
let width = rect[0].width;
let height = rect[0].height;
that.setData({
width,
height
});
const context = wx.createCanvasContext('firstCanvas')
that.setData({
context: context
})
context.save();
// context.translate(Math.ceil(width / 2) - 20,0)
context.setTransform(1, 0, 0, 1, Math.ceil(width / 2), 155);
context.rotate(Math.PI / 2);
let str = that.data.writeTips;
// context.fillText(str, Math.ceil((width - context.measureText(str).width) / 2), Math.ceil(height / 2) - 20)
context.setFontSize(24)
context.setFillStyle('#ADADB2');
// context.fillRect(0, 0, that.data.height, that.data.width);
context.fillText(str, 0, 0)
context.restore();
context.draw()
});
},
// 弹窗
onToast(){ app.toast(this, {
type: 'text',
text: '生成成功'
})
},
onShareAppMessage: (res) => { }
})

相关注释代码中都有,也么有优化,有好的方法,还希望大佬们多多指点

微信小程序电子签名实现的更多相关文章

  1. 微信小程序刚注册快速达到1000uv

    一.什么是微信小程序uv ​ UV:是累计独立访问,1个微信号就是一个uv,多次访问不算 ​ 大家想提升微信小程序uv都是为了开通流量主 二.流量主开通标准 ​ 达到1000uv就可以开通:严重违纪不 ...

  2. 微信小程序开发心得

    微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...

  3. 微信小程序体验(2):驴妈妈景区门票即买即游

    驴妈妈因为出色的运营能力,被腾讯选为首批小程序内测单位.驴妈妈的技术开发团队在很短的时间内完成了开发任务,并积极参与到张小龙团队的内测问题反馈.驴妈妈认为,移动互联网时代,微信是巨大的流量入口,也是旅 ...

  4. 微信小程序(微信应用号)组件讲解

    这篇文章主要讲解微信小程序的组件. 首先,讲解新建项目.现在有句话:招聘三天以上微信小程序开发,这个估计只能去挖微信的工程师了.技术新,既然讲解,那我们就从开始建项目讲解. 打开微信web开发者工具, ...

  5. 神技!微信小程序(应用号)抢先入门教程(附最新案例DEMO-豆瓣电影)持续更新

    微信小程序 Demo(豆瓣电影) 由于时间的关系,没有办法写一个完整的说明,后续配合一些视频资料,请持续关注 官方文档:https://mp.weixin.qq.com/debug/wxadoc/de ...

  6. 通过微信小程序看前端

    前言 2016年9月22日凌晨,微信官方通过“微信公开课”公众号发布了关于微信小程序(微信应用号)的内测通知.整个朋友圈瞬间便像炸开了锅似的,各种揣测.介绍性文章在一夜里诞生.而真正收到内测邀请的公众 ...

  7. 快速了解微信小程序的使用,一个根据小程序的框架开发的todos app

    微信官方已经开放微信小程序的官方文档和开发者工具.前两天都是在看相关的新闻来了解小程序该如何开发,这两天官方的文档出来之后,赶紧翻看了几眼,重点了解了一下文档中框架与组件这两个部分,然后根据简易教程, ...

  8. 来自于微信小程序的一封简讯

    9月21晚间,微信向部分公众号发出公众平台-微信应用号(小程序)的内测邀请,向来较为低调的微信在这一晚没人再忽视它了. 来自个人博客:Damonare的个人博客 一夜之间火了的微信应用号你真的知道吗? ...

  9. 微信小程序前端源码逻辑和工作流

    看完微信小程序的前端代码真的让我热血沸腾啊,代码逻辑和设计一目了然,没有多余的东西,真的是大道至简. 废话不多说,直接分析前端代码.个人观点,难免有疏漏,仅供参考. 文件基本结构: 先看入口app.j ...

随机推荐

  1. Java安全之Fastjson反序列化漏洞分析

    Java安全之Fastjson反序列化漏洞分析 首发:先知论坛 0x00 前言 在前面的RMI和JNDI注入学习里面为本次的Fastjson打了一个比较好的基础.利于后面的漏洞分析. 0x01 Fas ...

  2. 测试的V模型和W模型

    V模型 :后测试 优点: 1.每一阶段都清晰明了,便于把控开发的每一个过程. 2.既包含了单元测试又包含了系统测试 缺点: 1.测试介入的比较晚,所以开发前期的缺陷无从修改. 2.开发和测试串行. W ...

  3. Unity shader 护盾shield的简单实现

    先上效果图 shader所用的贴图资源 扰动 直接对uv进行变换就可以了,记得首先把六边形格子地图的Tilling调高点 先预先调成合适大小的六边形,然后repeat铺满整个护盾 // Tiles a ...

  4. C#是怎么跑起来的

    解释流程前,需要了解一些基本的概念. 基本概念解释: CPU :中央处理器,计算机的大脑,内部由数百万至数亿个晶体管组成,是解释和运行最终转换成机器语言(二进制代码)的地方.机器语言是通过CPU内存的 ...

  5. 排坑&#183;IPhone&IOS中不兼容正则中的断言匹配

    阅文时长 | 1.14分钟 字数统计 | 1834.4字符 主要内容 | 1.问题切入 2.什么是断言匹配 3.断言匹配的替换方案 4.声明与参考资料 『排坑·IPhone&IOS中不兼容正则 ...

  6. 【例 3】 修改 bols 文件的 atime 和 mtime。 [root@localhost ~]# touch -d "2017-05-04 15:44" bols

    Linux touch命令:创建文件及修改文件时间戳 < Linux删除空目录(rmdir命令)Linux在文件之间建立软/硬链接(ln命令) > <Linux就该这么学>是一 ...

  7. 2.1 CPU 上下文切换(上)

    cpu上下文与切换 进程在竞争 CPU 的时候并没有真正运行,为什么还会导致系统的负载升高呢?CPU 上下文切换就是罪魁祸首. 我们都知道,Linux 是一个多任务操作系统,它支持远大于 CPU 数量 ...

  8. MVC RadioButton控件

    @Html.RadioButtonFor(m => m.IfValid, 1, new { @id = "radio1", @name = "rdolstState ...

  9. centos7 启动docker失败

    现象:Centos7.3通过yum安装完docker后,启动docker失败 机器的系统版本:CentOS Linux release 7.3.1611 (Core) centos7,执行完安装命令: ...

  10. Spring Cloud 升级之路 - 2020.0.x - 7. 使用 Spring Cloud LoadBalancer (2)

    本项目代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们使用 Spri ...