pc端、手机端适配canvas绘图

原理

监听触摸滑动或鼠标滑动,在canvas上绘制出相应的笔迹

功能演示

HTML页面,下图灰色区域为绘制区,停止绘制后会在下方方框内生成图片

canvas绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<html>
<head>
<style>
.sign-box {
width: 200px;
}
.sign-box .sign-img {
width: 100%;
height: 100px;
}
.sign-box .btn-box>p {
width: 60px;
height: 20px;
line-height: 20px;
text-align: center;
display: inline-block;
}
</style>
</head>
<body>
<div class="sign-box">
<div class="sign-img" id="canvas">
</div>
<div class="btn-box">
<p id="btn-clear">清空</p>
<p id="btn-sub">确定</p>
</div>
<img class="sign-img" id="img">
</div>
</body>
</html>

canvas绘制后

绘制程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
let cxt = null;
// 签名笔记的基础样式
const lineStyle = {
lineWidth: 2,
strokeStyle: '#000000',
fillStyle: '#f7f7f7',
lineCap: 'round'
}
// 绘制区
const canvasEl = document.getElementById("canvas")
// 清空按钮
const clearBtn = document.getElementById("btn-clear")
// 提交按钮
const subBtn = document.getElementById("btn-sub")
lineCanvas({canvasEl, clearBtn, subBtn})
// 移动绘制
function lineCanvas({ canvasEl, clearBtn, subBtn }) {
const canvas = document.createElement("canvas");
canvas.width = canvasEl.clientWidth;
canvas.height = canvasEl.clientHeight;
canvasEl.appendChild(canvas);
cxt = canvas.getContext("2d");
console.log(cxt)
Object.keys(lineStyle).forEach(key => {
cxt[key] = lineStyle[key];
})
cxt.fillRect(0, 0, canvas.width, canvas.height)
IsPC() ? addMoveEvents(canvas) : addTouchEvents(canvas)
// 为【清除】按钮绑定点击事件,清空画布
clearBtn && clearBtn.addEventListener("click", function() {
console.log("清空画布...");
cxt.clearRect(0, 0, canvas.width, canvas.height);
document.getElementById("img").src = '';
})
// 为【确定】按钮绑定点击事件保存图片
subBtn && subBtn.addEventListener("click", function(e) {
console.log("保存图片...");
if(!signImg) {
alert("请签名")
return
}
// do somthing
})
}
// 判断当前是否是PC端
function IsPC() {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
var flag = true;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}

pc端鼠标按下绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 鼠标绘制
function addMoveEvents(canvas) {
// 鼠标按下事件
const mousedown = function(e) {
console.log("开始绘制...");
cxt.beginPath();
cxt.moveTo(e.pageX, e.pageY);
// 绘制中
canvas.addEventListener("mousemove", mousemove, false)
}
// 鼠标按下移动绘制事件
const mousemove = function(e) {
console.log("绘制中...");
cxt.lineTo(e.pageX, e.pageY);
cxt.stroke();
}
// 鼠标松开事件
const mouseup = function(e) {
console.log("结束绘制...");
canvas.removeEventListener("mousemove", mousemove)
cxt.closePath();
signImg = canvas.toDataURL();
console.log(signImg)
document.getElementById("img").src = signImg
}
// 阻止页面滑动
window.addEventListener('touchmove', function(e) {
e.preventDefault()
}, { passive: false });
// 监听绘制开始
canvas.addEventListener("mousedown", mousedown, false)
// 结束绘制
canvas.addEventListener("mouseup", mouseup, false)
// 鼠标移除画板后取消绘制时间
canvas.addEventListener("mouseout", function(e) {
console.log("鼠标移除画板");
canvas.removeEventListener("mousemove", mousemove)
})
}

mobile端触摸绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 触摸绘制
function addTouchEvents(canvas) {
// 手指点下开始事件
const touchstart = function(e) {
console.log("开始绘制...");
cxt.beginPath();
cxt.moveTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
}
// 触摸移动绘制事件
const touchmove = function(e) {
console.log("绘制中...");
cxt.lineTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
cxt.stroke();
}
// 手指移开事件
const touchend = function(e) {
console.log("结束绘制...");
cxt.closePath();
signImg = canvas.toDataURL();
console.log(signImg)
document.getElementById("img").src = signImg
}
// 监听绘制开始
canvas.addEventListener("touchstart", touchstart, false)
// 绘制中
canvas.addEventListener("touchmove", touchmove, false)
// 结束绘制
canvas.addEventListener("touchend", touchend, false)
}

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<html>
<head>
<style>
.sign-box {
width: 200px;
}
.sign-box .sign-img {
width: 100%;
height: 100px;
}
.sign-box .btn-box>p {
width: 60px;
height: 20px;
line-height: 20px;
text-align: center;
display: inline-block;
}
</style>
</head>
<body>
<div class="sign-box">
<div class="sign-img" id="canvas">
</div>
<div class="btn-box">
<p id="btn-clear">清空</p>
<p id="btn-sub">确定</p>
</div>
<img class="sign-img" id="img">
</div>
<script>
let cxt = null;
const lineStyle = {
lineWidth: 2,
strokeStyle: '#000000',
fillStyle: '#f7f7f7',
lineCap: 'round'
}
const canvasEl = document.getElementById("canvas")
const clearBtn = document.getElementById("btn-clear")
const subBtn = document.getElementById("btn-sub")
window.addEventListener('touchmove', function(e) {
e.preventDefault()
}, { passive: false });
lineCanvas({canvasEl, clearBtn, subBtn})
// 移动绘制
function lineCanvas({ canvasEl, clearBtn, subBtn }) {
const canvas = document.createElement("canvas");
canvas.width = canvasEl.clientWidth;
canvas.height = canvasEl.clientHeight;
canvasEl.appendChild(canvas);
cxt = canvas.getContext("2d");
console.log(cxt)
Object.keys(lineStyle).forEach(key => {
cxt[key] = lineStyle[key];
})
cxt.fillRect(0, 0, canvas.width, canvas.height)
IsPC() ? addMoveEvents(canvas) : addTouchEvents(canvas)
// 清空画布
clearBtn && clearBtn.addEventListener("click", function() {
console.log("清空画布...");
cxt.clearRect(0, 0, canvas.width, canvas.height);
document.getElementById("img").src = '';
})
// 保存图片
subBtn && subBtn.addEventListener("click", function(e) {
console.log("保存图片...");
if(!signImg) {
alert("请签名")
return
}
// do somthing
})
}
// 鼠标绘制
function addMoveEvents(canvas) {
// 鼠标按下事件
const mousedown = function(e) {
console.log("开始绘制...");
cxt.beginPath();
cxt.moveTo(e.pageX, e.pageY);
// 绘制中
canvas.addEventListener("mousemove", mousemove, false)
}
// 鼠标按下移动绘制事件
const mousemove = function(e) {
console.log("绘制中...");
cxt.lineTo(e.pageX, e.pageY);
cxt.stroke();
}
// 鼠标松开事件
const mouseup = function(e) {
console.log("结束绘制...");
canvas.removeEventListener("mousemove", mousemove)
cxt.closePath();
signImg = canvas.toDataURL();
console.log(signImg)
document.getElementById("img").src = signImg
}
// 监听绘制开始
canvas.addEventListener("mousedown", mousedown, false)
// 结束绘制
canvas.addEventListener("mouseup", mouseup, false)
// 鼠标移除画板后取消绘制时间
canvas.addEventListener("mouseout", function(e) {
console.log("鼠标移除画板");
canvas.removeEventListener("mousemove", mousemove)
})
}
// 触摸绘制
function addTouchEvents(canvas) {
// 手指点下开始事件
const touchstart = function(e) {
console.log("开始绘制...");
cxt.beginPath();
cxt.moveTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
}
// 触摸移动绘制事件
const touchmove = function(e) {
console.log("绘制中...");
cxt.lineTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
cxt.stroke();
}
// 手指移开事件
const touchend = function(e) {
console.log("结束绘制...");
cxt.closePath();
signImg = canvas.toDataURL();
console.log(signImg)
document.getElementById("img").src = signImg
}
// 监听绘制开始
canvas.addEventListener("touchstart", touchstart, false)
// 绘制中
canvas.addEventListener("touchmove", touchmove, false)
// 结束绘制
canvas.addEventListener("touchend", touchend, false)
}
function IsPC() {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
var flag = true;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
</script>
</body>
</html>

最后更新: 2021年12月08日 19:55