<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<canvas></canvas>
<div>
<button onclick="cancel()">取消</button>
<button onclick="save()">保存</button>
</div>
</body>
<script>
// 配置内容
const config = {
width: 400, // 宽度
height: 200, // 高度
lineWidth: 5, // 线宽
strokeStyle: 'red', // 线条颜色
lineCap: 'round', // 设置线条两端圆角
lineJoin: 'round', // 线条交汇处圆角
} // 获取canvas 实例
const canvas = document.querySelector('canvas')
// 设置宽高
canvas.width = config.width
canvas.height = config.height
// 设置一个边框
canvas.style.border = '1px solid #000'
// 创建上下文
const ctx = canvas.getContext('2d') // 设置填充背景色
ctx.fillStyle = 'transparent'
// 绘制填充矩形
ctx.fillRect(
0, // x 轴起始绘制位置
0, // y 轴起始绘制位置
config.width, // 宽度
config.height // 高度
); // 保存上次绘制的 坐标及偏移量
const client = {
offsetX: 0, // 偏移量
offsetY: 0,
endX: 0, // 坐标
endY: 0
} // 判断是否为移动端
const mobileStatus = (/Mobile|Android|iPhone/i.test(navigator.userAgent)) // 初始化
const init = event => {
// 获取偏移量及坐标
const { offsetX, offsetY, pageX, pageY } = mobileStatus ? event.changedTouches[0] : event // 修改上次的偏移量及坐标
client.offsetX = offsetX
client.offsetY = offsetY
client.endX = pageX
client.endY = pageY // 清除以上一次 beginPath 之后的所有路径,进行绘制
ctx.beginPath()
// 根据配置文件设置相应配置
ctx.lineWidth = config.lineWidth
ctx.strokeStyle = config.strokeStyle
ctx.lineCap = config.lineCap
ctx.lineJoin = config.lineJoin
// 设置画线起始点位
ctx.moveTo(client.endX, client.endY)
// 监听 鼠标移动或手势移动
window.addEventListener(mobileStatus ? "touchmove" : "mousemove", draw)
}
// 绘制
const draw = event => {
// 获取当前坐标点位
const { pageX, pageY } = mobileStatus ? event.changedTouches[0] : event
// 修改最后一次绘制的坐标点
client.endX = pageX
client.endY = pageY // 根据坐标点位移动添加线条
ctx.lineTo(pageX , pageY ) // 绘制
ctx.stroke()
}
// 结束绘制
const cloaseDraw = () => {
// 结束绘制
ctx.closePath()
// 移除鼠标移动或手势移动监听器
window.removeEventListener("mousemove", draw)
}
// 创建鼠标/手势按下监听器
window.addEventListener(mobileStatus ? "touchstart" : "mousedown", init)
// 创建鼠标/手势 弹起/离开 监听器
window.addEventListener(mobileStatus ? "touchend" :"mouseup", cloaseDraw) // 取消-清空画布
const cancel = () => {
// 清空当前画布上的所有绘制内容
ctx.clearRect(0, 0, config.width, config.height)
}
// 保存-将画布内容保存为图片
const save = () => {
// 将canvas上的内容转成blob流
canvas.toBlob(blob => {
// 获取当前时间并转成字符串,用来当做文件名
const date = Date.now().toString()
// 创建一个 a 标签
const a = document.createElement('a')
// 设置 a 标签的下载文件名
a.download = `${date}.png`
// 设置 a 标签的跳转路径为 文件流地址
a.href = URL.createObjectURL(blob)
// 手动触发 a 标签的点击事件
a.click()
// 移除 a 标签
a.remove()
})
}
</script>
</html>

  

前端实现电子签名(web、移动端)通用组件(canvas实现)的更多相关文章

  1. 饿了么基于Vue2.0的通用组件开发之路(分享会记录)

    Element:一套通用组件库的开发之路 Element 是由饿了么UED设计.饿了么大前端开发的一套基于 Vue 2.0 的桌面端组件库.今天我们要分享的就是开发 Element 的一些心得. 官网 ...

  2. 前端文摘:Web 开发模式演变历史和趋势

    今天的<前端文摘>给大家分享一篇玉伯的文章.文章详细介绍了 Web 开发的四种常用模式以及未来可能成为流行趋势的 Node 全栈开发模式,相信你看了以后一定会有收获. 您可能感兴趣的相关文 ...

  3. Web服务端软件的服务品质概要

    软件品质概述 提供同样功能.产品和服务的服务者中, 竞争力来自功能的多样化和服务品质的差异化, 无论是个体.企业还是国家. 这里的服务指功能.产品的实现程度和处理能力,以及研发/客服提供的技术支持程度 ...

  4. Vue2.0的通用组件

    饿了么基于Vue2.0的通用组件开发之路(分享会记录)   Element:一套通用组件库的开发之路 Element 是由饿了么UED设计.饿了么大前端开发的一套基于 Vue 2.0 的桌面端组件库. ...

  5. JS前端图形化插件之利器Gojs组件(php中文网)

    JS前端图形化插件之利器Gojs组件(php中文网) 一.总结 一句话总结:php中文网我可以好好走一波 二.JS前端图形化插件之利器Gojs组件 参考: JS前端图形化插件之利器Gojs组件-js教 ...

  6. 关于如何提高Web服务端并发效率的异步编程技术

    最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...

  7. HT for Web的HTML5树组件延迟加载技术实现

    HT for Web的HTML5树组件有延迟加载的功能,这个功能对于那些需要从服务器读取具有层级依赖关系数据时非常有用,需要获取数据的时候再向服务器发起请求,这样可减轻服务器压力,同时也减少了浏览器的 ...

  8. Openstack的web管理端相关

    openstack的web管理端技术方面要关注的问题. 同步?异步 先说浏览器的同步和异步,我们知道的浏览器可以使用ajax实现异步请求,就是浏览器在请求数据的时候,我们管理员还能对浏览器就行其他操作 ...

  9. 从web移动端布局到react native布局

    在web移动端通常会有这样的需求,实现上中下三栏布局(上下导航栏位置固定,中间部分内容超出可滚动),如下图所示: 实现方法如下: HTML结构: <div class='container'&g ...

  10. 【译】编写支持SSR的通用组件指南

    原文来自:https://blog.lichter.io/posts/the-guide-to-write-universal-ssr-ready-vue-compon?utm_campaign=Vu ...

随机推荐

  1. 基于 VScode 搭建 Verilog 自动格式化

    插件 Verilog-HDL/SystemVerilog/Bluespec SystemVerilog SystemVerilog and Verilog Formatter 工具 https://g ...

  2. three.js实现分模块添加梦幻bloom辉光光晕方案--详细注释版本~~方案三版本~~

    先上图对比方案1-2-3不同点,本文是方案3 方案1(旋转场景情况下发光体不应该遮住另一个,但是遮住了) 方案2(层次正常,发光正常) 方案3(层次正常,发光正常,但是转动场景时候部分辉光会被遮挡,但 ...

  3. 最新编程语言排名Python、C、Java 和 C++ 已形成四足鼎立之势

    引言 技术的千变万化,都是有迹可循的,随着最新的 TIOBE 十月编程语言榜单重磅发布,不同开发语言的排名和发展趋势也随之揭晓! 四大编程语言不断增强其主导地位 曾几何时,编程语言界中 Java.C. ...

  4. wsl2和ArchLinux的安装

    版权声明:本文章参考了哔哩哔哩稿件BV1sW411v7VZ,如侵权请主动联系删除 1.Wsl2的安装 启用适用于 Linux 的 Windows 子系统 在终端运行:dism.exe /online ...

  5. 11月18日内容总结——同步、异步与阻塞、非阻塞的概念、创建进程的多种方式及multiprocessing模块、进程间的数据隔离和IPC机制(队列)、生产者消费者模型、守护进程、僵尸进程、孤儿进程和多进程错乱问题

    目录 一.同步与异步 同步 异步 二.阻塞与非阻塞 阻塞 非阻塞 三.综合使用 1.同步阻塞: 2.同步非阻塞: 3.异步阻塞: 4.异步非阻塞: 四.创建进程的多种方式 进程的创建 multipro ...

  6. idea2022.2.3安装破解

    转:https://www.quanxiaoha.com/article/idea-pojie.html 1 注意事项 如果是卸载了旧版本安装的本版本,安装完成后打不开,可能是旧版本的影响 找到:C: ...

  7. STM32F4跳转函数

    JMP2APP void JMP2APP(void) { pFunction Jump_To_Application; uint32_t JumpAddress; if (((*(__IO uint3 ...

  8. ctfshow_web入门 PHP特性

    PHP特性 这里以半做题,半学习为主,所以就显得比较啰嗦 阿巴阿巴,但是实际上,写得比较水,等过一段时间再总结一下 比较深刻的印象是:下一个手册,多看手册 从web135还是几开始,就是看的这个师傅的 ...

  9. JZOJ 3528. 【NOIP2013模拟11.7A组】图书馆(library)

    题目 解析 看到这题,没想到 \(dp\) 果断打了暴力 暴力理应只有 \(30\) 左右的样子 然而我加上了些奇技淫巧竟然有 \(80\) 分! 惊到我了! 我 \(80\) 分的暴力: 很容易想到 ...

  10. Swiper第一页与最后一页禁止滑动

    resistanceRatio抵抗率.边缘抵抗力的大小比例.值越小抵抗越大越难将slide拖离边缘,0时完全无法拖离. mounted: function() { let _this = this; ...