<!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>

  

最新文章

  1. Ubuntu解压缩命令
  2. Gerrit与Gitlab同步配置replication&amp;其他配置
  3. scp使用
  4. libsvm参数学习和核函数使用(转载)
  5. log4net 中错误 System.Web.HttpException (0x80004005): 文件不存在
  6. Hibernate连接mysql数据库并自动创建表
  7. SuperGridControl 使用小技巧
  8. C#自定义时间显示格式
  9. 在AngularJS的controller外部直接获取$scope
  10. [AngularJS] Angular 1.5 multiple transclude
  11. [TYVJ] P1026 犁田机器人
  12. Android 4.2启动代码分析(一)
  13. oracle表空间查询维护命令大全之三(暂时表空间)史上最全
  14. centos gdb安装
  15. python学习之字典(Dictionary)练习
  16. jQuery的学习笔记
  17. S2-045漏洞初步分析
  18. 2019元月新SAP项目落地记
  19. SQL Server 2012还原一直卡在ASYNC_IO_COMPLETION浅析
  20. Confluence 6 安全概述和建议概述

热门文章

  1. FalseSharing-伪共享
  2. 图文并茂解决Client does not support authentication protocol requested by server; consider upgrading MySQL
  3. Array.from() ------来自❀ 前端宇宙 ❀公众号。
  4. djiango路由匹配、djiango路由层、反向解析、有名无名反向解析
  5. DNS 是如何影响你冲浪速度的?
  6. 手把手教大家写书写一个Mqtt网关
  7. 【Android 4.4】内存文件系统(tmpfs)的创建与使用
  8. JavaScript 评测代码运行速度
  9. Windows Server 2016 安装AD和Exchange
  10. ChatGPT调研分析与应用场域结合构想