微信小程序电子签名实现
实现签名方法就是使用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) => { }
})
相关注释代码中都有,也么有优化,有好的方法,还希望大佬们多多指点
微信小程序电子签名实现的更多相关文章
- 微信小程序刚注册快速达到1000uv
一.什么是微信小程序uv UV:是累计独立访问,1个微信号就是一个uv,多次访问不算 大家想提升微信小程序uv都是为了开通流量主 二.流量主开通标准 达到1000uv就可以开通:严重违纪不 ...
- 微信小程序开发心得
微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...
- 微信小程序体验(2):驴妈妈景区门票即买即游
驴妈妈因为出色的运营能力,被腾讯选为首批小程序内测单位.驴妈妈的技术开发团队在很短的时间内完成了开发任务,并积极参与到张小龙团队的内测问题反馈.驴妈妈认为,移动互联网时代,微信是巨大的流量入口,也是旅 ...
- 微信小程序(微信应用号)组件讲解
这篇文章主要讲解微信小程序的组件. 首先,讲解新建项目.现在有句话:招聘三天以上微信小程序开发,这个估计只能去挖微信的工程师了.技术新,既然讲解,那我们就从开始建项目讲解. 打开微信web开发者工具, ...
- 神技!微信小程序(应用号)抢先入门教程(附最新案例DEMO-豆瓣电影)持续更新
微信小程序 Demo(豆瓣电影) 由于时间的关系,没有办法写一个完整的说明,后续配合一些视频资料,请持续关注 官方文档:https://mp.weixin.qq.com/debug/wxadoc/de ...
- 通过微信小程序看前端
前言 2016年9月22日凌晨,微信官方通过“微信公开课”公众号发布了关于微信小程序(微信应用号)的内测通知.整个朋友圈瞬间便像炸开了锅似的,各种揣测.介绍性文章在一夜里诞生.而真正收到内测邀请的公众 ...
- 快速了解微信小程序的使用,一个根据小程序的框架开发的todos app
微信官方已经开放微信小程序的官方文档和开发者工具.前两天都是在看相关的新闻来了解小程序该如何开发,这两天官方的文档出来之后,赶紧翻看了几眼,重点了解了一下文档中框架与组件这两个部分,然后根据简易教程, ...
- 来自于微信小程序的一封简讯
9月21晚间,微信向部分公众号发出公众平台-微信应用号(小程序)的内测邀请,向来较为低调的微信在这一晚没人再忽视它了. 来自个人博客:Damonare的个人博客 一夜之间火了的微信应用号你真的知道吗? ...
- 微信小程序前端源码逻辑和工作流
看完微信小程序的前端代码真的让我热血沸腾啊,代码逻辑和设计一目了然,没有多余的东西,真的是大道至简. 废话不多说,直接分析前端代码.个人观点,难免有疏漏,仅供参考. 文件基本结构: 先看入口app.j ...
随机推荐
- 封装了一些sqlsugar的常用方法 用来动态切换数据库和依赖注入 支持泛型
接口: /// <summary> /// 数据库操作 /// </summary> public interface IDAL_Services { /// <summ ...
- Duplicate entry '' for key 'PRIMARY'
今天在在mysql中插入数据 因为直接插入查询出来的表格,insert into 表(student_id,class_id) 直接插入了这两个字段对应的查询出来的表 没有留意到该表的主键没有设置自增 ...
- 关于flask的模板注入的学习
flask模板注入的学习 关于flask模版注入,之前不太理解,看了很多文章才弄懂,主要原理就是渲染函数的参数用户可控就造成了模板注入 就会使用户构造恶意的代码进行逃逸从而进行攻击 flask模板渲染 ...
- [Java] 数据分析--数据预处理
数据结构 键-值对:HashMap 1 import java.io.File; 2 import java.io.FileNotFoundException; 3 import java.util. ...
- [笔记] 《c++ primer》显示器程序 Chapter7
补充Sales_data没有体现出的其他类特性 Screen.h 1 #include <string> 2 #include <iostream> 3 4 class Scr ...
- [Java] Structs
背景 基于MVC的WEB框架 在表示层过滤访问请求并处理 步骤 在eclipse中创建Web动态项目 导入相关jar包到WEB-INF/lib 在WEB-INF目录下新建web.xml,配置Filte ...
- C++知识点案例 笔记-6
1.三种友元函数 -非模板友元函数 -约束模板友元函数 -非约束模板友元函数 2.非类型参数 3.模板特化 1.三种友元函数 =====三种友元函数===== --1---非模板友元函数 #inclu ...
- Java EnumMap 实现类
EnumMap 实现类 因为 HashMap 是一种通过对 key 计算 hashCode(),通过空间换时间的方式,直接定位到 value 所在的内部数组的索引,因此,查找效率非常高. 如果作为 k ...
- CAP 与数据一致性
分布式系统的假设是,工作在网络环境下的系统拥有多个节点,而这些节点本身会由于各种原因而变得不稳定.这其中就有一个非常重要的概念--CAP原理.这个原理指导着大多数分布式系统的设计过程,CAP原理大致是 ...
- 灵动微电子ARM Cortex M0 MM32F0010 GPIO 的配置驱动LED灯
灵动微电子ARM Cortex M0 MM32F0010 GPIO的配置 目录: 1.前言 2.学习方法简要说明 3.要点提示 4.注意事项 5.MM32F0010系统时钟的配置 6.MM32F001 ...