js版本

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head> <body>
<div id="app">
<div class="sign-page">
<div class="canvas-box">
<div class="canvas" ontouchstart="methods.canvasTouchEvent(event,'canvasStart')"
ontouchmove="methods.canvasTouchEvent(event,'canvasMove')"
ontouchend="methods.canvasTouchEvent(event,'canvasEnd')">
<div class="title">请在该区域内工整书写您的签名</div>
</div>
</div>
<p class="clearCanvas" onclick="methods.saveOrClear('clear')">清 除</p>
<p class="saveCanvas" onclick="methods.saveOrClear('save')">保 存</p>
</div>
</div>
<script> const temp = {
canvas: null, // 画布el对象
cxt: null, // 上下文
stageInfo: null, // 返回canvas的大小及位置
isSign: false //未签名提示
} const data = new Proxy(temp, {
set(target, property, value, receiver) {
if (property === 'isSign') {
console.log(value);
document.querySelector('.title').style.display = value ? 'none' : 'block'
}
return Reflect.set(target, property, value); },
get(target, key) {
return Reflect.get(target, key);
},
}) const methods = {
/*
* 画布初始化事件
*/
initCanvas(obj) {
data.canvas = document.createElement('canvas'); // 指定canvas
obj.el.appendChild(data.canvas);
data.cxt = data.canvas.getContext('2d'); // 设置2D渲染区域
data.canvas.width = obj.el.clientWidth;
data.canvas.height = obj.el.clientHeight;
data.cxt.fillStyle = '#ffffff';
data.cxt.strokeStyle = '#000000';
data.cxt.fillRect(0, 0, data.canvas.width, data.canvas.width);
data.cxt.lineWidth = 2; // 设置线的宽度
data.cxt.lineCap = 'round';
data.stageInfo = data.canvas.getBoundingClientRect();
},
/*
* 画布touch相关事件处理
*/
canvasTouchEvent(e, type) {
const cxt = data.cxt;
const postion = [e.changedTouches[0].pageX - data.stageInfo.left, e.changedTouches[0].pageY - data.stageInfo.top]
const handle = {
canvasStart: () => {
cxt.beginPath();
cxt.moveTo(...postion);
},
canvasMove: () => {
if (!e && !e.preventDefault) return;
e.preventDefault();
cxt.lineTo(...postion);
cxt.stroke();
data.isSign = true;
},
canvasEnd: () => cxt.closePath
}
handle[type]();
}, /*
* 清除和保存事件
*/
saveOrClear(type) {
if (type === 'clear') {
data.cxt.clearRect(0, 0, data.canvas.width, data.canvas.height);
data.isSign = false;
return false;
} if (data.isSign) {
const imgBase64 = data.canvas.toDataURL();
console.log(imgBase64);
} else {
data.$dialog.alert({ title: '错误', message: '请绘制签名', messageAlign: 'center' });
}
}
} const p = new Proxy(data, {
set(target, property, value, receiver) {
console.log(key);
if (property === 'isSign') {
console.log('isSign');
}
return Reflect.set(target, key, value); }
}) setTimeout(() => {
methods.initCanvas({ el: document.querySelector('.canvas') });
}) </script>
<style>
.canvas-box {
width: calc(100% - 68px);
height: calc(100% - 180px);
margin-bottom: 38px;
position: relative;
border-radius: 6px;
background: #fff;
padding: 34px; } .canvas {
background: #fff;
height: 100%;
width: 100%;
border: 1px dashed #848588;
position: relative;
border-radius: 6px;
} .saveCanvas,
.clearCanvas {
padding: 10px 0;
background: rgba(207, 225, 245, 1);
width: 45%;
text-align: center;
float: left;
color: #3F8EE8;
} .saveCanvas {
margin-left: 10%;
} .sign-page {
background: #EDF1F6;
width: calc(100% - 60px);
height: calc(100% - 96px);
padding: 58px 30px 38px;
position: fixed;
top: 0;
left: 0;
} .title {
text-orientation: mixed;
font-size: 18px;
color: #A0ACBF;
position: absolute;
padding: 10%;
top: 0;
left: 0;
}
</style>
</body> </html>

vue版

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head> <body>
<div id="app">
<div class="sign-page">
<div class="canvas-box">
<div class="canvas" ref="canvas" @touchstart="canvasTouchEvent($event,'canvasStart')"
@touchmove="canvasTouchEvent($event,'canvasMove')" @touchend="canvasTouchEvent($event,'canvasEnd')">
<div class="title" v-if="!isSign">请在该区域内工整书写您的签名</div>
</div>
</div>
<p class="clearCanvas" @click="saveOrClear('clear')">清 除</p>
<p class="saveCanvas" @click="saveOrClear('save')">保 存</p>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script> const app = new Vue({
el: '#app',
data: {
canvas: null, // 画布el对象
cxt: null, // 上下文
stageInfo: null, // 返回canvas的大小及位置
isSign: false //未签名提示
},
methods: {
/*
* 画布初始化事件
*/
initCanvas(obj) {
this.canvas = document.createElement('canvas'); // 指定canvas
obj.el.appendChild(this.canvas);
this.cxt = this.canvas.getContext('2d'); // 设置2D渲染区域
this.canvas.width = obj.el.clientWidth;
this.canvas.height = obj.el.clientHeight;
this.cxt.fillStyle = '#ffffff';
this.cxt.strokeStyle = '#000000';
this.cxt.fillRect(0, 0, this.canvas.width, this.canvas.width);
this.cxt.lineWidth = 2; // 设置线的宽度
this.cxt.lineCap = 'round';
this.stageInfo = this.canvas.getBoundingClientRect();
},
/*
* 画布touch相关事件处理
*/
canvasTouchEvent(e, type) {
const cxt = this.cxt;
const postion = [e.changedTouches[0].pageX - this.stageInfo.left, e.changedTouches[0].pageY - this.stageInfo.top]
const handle = {
canvasStart: () => {
cxt.beginPath();
cxt.moveTo(...postion);
},
canvasMove: () => {
if (!e && !e.preventDefault) return;
e.preventDefault();
cxt.lineTo(...postion);
cxt.stroke();
this.isSign = true;
},
canvasEnd: () => cxt.closePath
}
handle[type]();
}, /*
* 清除和保存事件
*/
saveOrClear(type) {
if (type === 'clear') {
this.cxt.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.isSign = false;
return false;
} if (this.isSign) {
const imgBase64 = this.canvas.toDataURL();
console.log(imgBase64);
} else {
this.$dialog.alert({ title: '错误', message: '请绘制签名', messageAlign: 'center' });
}
}
},
mounted() {
setTimeout(() => {
this.initCanvas({ el: this.$refs.canvas });
})
}
})
</script>
<style>
.canvas-box {
width: calc(100% - 68px);
height: calc(100% - 180px);
margin-bottom: 38px;
position: relative;
border-radius: 6px;
background: #fff;
padding: 34px; } .canvas {
background: #fff;
height: 100%;
width: 100%;
border: 1px dashed #848588;
position: relative;
border-radius: 6px;
} .saveCanvas,
.clearCanvas {
padding: 10px 0;
background: rgba(207, 225, 245, 1);
width: 45%;
text-align: center;
float: left;
color: #3F8EE8;
} .saveCanvas {
margin-left: 10%;
} .sign-page {
background: #EDF1F6;
width: calc(100% - 60px);
height: calc(100% - 96px);
padding: 58px 30px 38px;
position: fixed;
top: 0;
left: 0;
} .title {
text-orientation: mixed;
font-size: 18px;
color: #A0ACBF;
position: absolute;
padding: 10%;
top: 0;
left: 0;
}
</style>
</body> </html>
 

效果图

html手写板的更多相关文章

  1. Python3使用PyQt5制作简单的画板/手写板

    0.目录 1.前言 2.简单的画板1.0 在定点和移动中的鼠标所在处画一条线 3.简单的画板2.0 在定点和移动中的鼠标所在处画一条线 并将画过的线都保留在窗体上 4.简单的画板3.0 将按住鼠标后移 ...

  2. 【微信小程序canvas】实现小程序手写板用户签名(附代码)

    工作中公司业务需要的微信小程序用户签字功能 先看效果图: wxml: <view class="wrapper"> <view class="handB ...

  3. h5简易手写板

    ............. 我该说点什么呢,开头居然不知道想说点什么!好吧不知道说什么,我们就来说说这个手写板吧,虽然这个手写板现在没什么用,但是.....,好像的确没什么用啊! 只是存粹哪里练手的的 ...

  4. Android 实现手写板技术

    Android手写板和涂鸦的功能,代码如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/andro ...

  5. 在 浏览器中调用外接设备— —手写板 【win10 x64 手动注册ocx控件的方法】

    PPAXSignToolSDK.ocx 浏览器下使用手写板时调用的控件,使用前必须先注册,,不然浏览器下版本无法正常工作. ocx 控件在安装包运行时会自动注册,如果安装包没有注册成功,需要进行手动注 ...

  6. 吴恩达讲了干货满满的一节全新AI课,全程手写板书充满诚意非常干货

    吴恩达讲了干货满满的一节全新AI课,全程手写板书充满诚意非常干货 摘要: 目前,AI技术做出的经济贡献几乎都来自监督学习,也就是学习从A到B,从输入到输出的映射.现在,监督学习.迁移学习.非监督学习. ...

  7. C# Winform 中如何获取本机安装输入法,并设置为默认输出语言,如何打开搜狗输入法和手写板

    一.问题: 今天,我整理了一下两个问题 1.如何获取本机安装所有输入法,并设置为系统输出语言 2.如何打开搜狗拼音输入法工具栏和手写板: 二.解决方法 比如:我们要设置搜狗输入法为本机输入语言,要怎么 ...

  8. C# ASP.NET 手写板并生成图片保存

    前端: @{ Layout = null; } <!DOCTYPE html> <html lang="zh-CN"> <head> <t ...

  9. myScript调研,电子手写板使用,纯干货

    第二天进公司,就叫我调研myScript作为手写板的可行性,又不能不做,哎~ myScript效果十分的奈斯,前端用canvas手写的文字.数学字符,都可以识别然后转换,不知道myScript是不是你 ...

  10. 基于myscript.js的web手写板(支持中文识别)

    网上的手写板模板不少,但是支持中文识别的却不多,而且基本上都收费的,毕竟别人的中文库凭什么免费提供给你(说好的开源呢?说好的开源呢? ←_←) 好了,进入主题,myscript.js,在官网其实我并没 ...

随机推荐

  1. Mybatis的动态SQL的语句

    例子. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC &quo ...

  2. Navicat Premium 16无限试用教程

    1.前往官网下载[Navicat Premium 16] http://www.navicat.com.cn/products 2.创建清理试用信息bat Navicat Premium 16Crac ...

  3. 在MaxKB中实现准确的Chat TO SQL(BI)

    主要面向考试成绩管理系统(目前支持旭日图.仪表盘柱状图.桑基图.漏斗图.河流图.数据聚合图.散点图.南丁格尔玫瑰图.饼状图.环形图.堆叠柱状图.堆叠折线图.堆叠面积图.面积图.折线图) 主要思路: 第 ...

  4. Sentinel源码—2.Context和处理链的初始化

    大纲 1.Sentinel底层的核心概念 2.Sentinel中Context的设计思想与源码实现 3.Java SPI机制的引入 4.Java SPI机制在Sentinel处理链中的应用 5.Sen ...

  5. 2025dsfz集训Day4:BFS及其优化

    DAY4: BFS及其优化 \[Designed\ By\ FrankWkd\ -\ Luogu@Lwj54joy,uid=845400 \] 特别感谢 此次课的主讲 - Kwling BFS 广度优 ...

  6. PHP中的精确计算bcadd,bcsub,bcmul,bcdiv 及 扩展安装

    <?php/** * 精确加法 * @param [type] $a [description] * @param [type] $b [description] */function math ...

  7. SpringCloud项目使用nacos配置

    SpringCloud项目 pom.xml 注意SpringCloud和SpringCloudAlibaba的版本对应. Spring Cloud Alibaba Version Spring Clo ...

  8. 通过adb访问SQLite数据库

    根据<第一行代码>第二版进入到数据库的文件夹,但是如果照书本直接cd data/data/包名/databases 的话是会报错的,错误信息如下 cd: /data/data/包名 /da ...

  9. Spring--IOC注解用法初探

    创建一个UserDao接口,和一个UserDaoImp的实现类 UserDao接口 package com.zjw.spring.demo1; public interface UserDao { p ...

  10. WPF学习问题汇集:

    WPF中ItemsSource改变,DataGrid中不更新 需要将ItemsSource先赋值为null,而后再赋值为新的值. 例如: gridBeamInfo.ItemsSource = null ...