PC端鼠标版本
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<style type="text/css">
* {margin: 0;padding: 0;}
.music-play {margin: 100px;}
.music-play canvas {border: 1px solid #ccc;}
.btns {text-align: center;}
.btn {width: 100px;display: inline-block;margin-right: 20px;background-color: red;
height: 50px;line-height: 50px;color: #fff;}
</style>
</head>
<body>
<div class="music-play">
<canvas width="500" height="500"></canvas>
</div>
<div class="btns">
<div class="btn" onclick="reset()">重置</div>
<div class="btn" onclick="down()">下载</div>
</div>
</body>
<script type="text/javascript">
window.onload = function() {
const oc = document.querySelector('canvas');
oc.width = document.documentElement.offsetWidth * 0.8;
if (oc.getContext('2d')) {
const ctx = oc.getContext('2d');
ctx.save();
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, oc.width, oc.height);
ctx.restore();
ctx.strokeStyle = "#ff0000";
ctx.lineWidth = 3;
oc.onmousedown = function(e) {
ctx.beginPath();
ctx.moveTo(e.clientX - oc.offsetLeft, e.clientY - oc.offsetTop);
oc.onmousemove = function(e) {
ctx.lineTo(e.clientX - oc.offsetLeft, e.clientY - oc.offsetTop);
ctx.stroke();
};
oc.onmouseup = function(e) {
oc.onmousemove = null;
}
}
}
}
function reset() {
const oc = document.querySelector('canvas');
if (oc.getContext('2d')) {
const ctx = oc.getContext('2d');
ctx.clearRect(0, 0, oc.width, oc.height);
}
}
function down() {
const oc = document.querySelector('canvas');
var a = document.createElement('a');
a.download = '电子签名';
a.href = oc.toDataURL('image/jpeg');
a.click();
}
</script>
</html>
移动端版本:抗锯齿
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<style type="text/css">
* {margin: 0;padding: 0;}
html, body {height: 100%;overflow: hidden;}
.music-play {width: 90%;margin: 0 auto;border: 1px solid #ccc;margin-bottom: 30px;margin-top: 20px;}
.btns {text-align: center;}
.btn {width: 100px;display: inline-block;margin-right: 20px;background-color: red;
height: 36px;line-height: 36px;color: #fff;}
.btn:last-child {margin-right: 0;}
</style>
</head>
<body>
<div class="music-play">
<canvas height="600" width="1068" style=" 356px; height: 544px;"></canvas>
</div>
</body>
<script type="text/javascript">
window.onload = function() {
const oc = document.querySelector('canvas');
if (oc.getContext('2d')) {
const ctx = oc.getContext('2d');
ctx.save();
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, oc.width, oc.height);
ctx.restore();
oc.ontouchstart = function(e) {
ctx.beginPath();
const {clientX, clientY} = e.changedTouches[0];
ctx.moveTo(clientX - oc.offsetLeft, clientY - oc.offsetTop);
oc.ontouchmove = function(e) {
const {clientX, clientY} = e.changedTouches[0];
ctx.lineTo(clientX - oc.offsetLeft, clientY - oc.offsetTop);
ctx.stroke();
};
oc.ontouchend = function(e) {
oc.ontouchmove = null;
}
}
// 根据设备像素比优化canvas绘图
const {width, height} = oc;
const devicePixelRatio = window.devicePixelRatio;
if (devicePixelRatio) {
oc.style.width = `${width}px`;
oc.style.height = `${height}px`;
oc.height = height * devicePixelRatio; // 画布宽高放大
oc.width = width * devicePixelRatio;
ctx.scale(devicePixelRatio, devicePixelRatio); // 画布内容放大相同的倍数
} else {
oc.width = width;
oc.height = height;
}
ctx.strokeStyle = "#ff0000";
ctx.lineWidth = 6;
ctx.lineCap = 'round'; // 直线首尾端圆滑
ctx.lineJoin = 'round'; // 当两条线条交汇时,创建圆形边角
ctx.shadowBlur = 1; // 边缘模糊,防止直线边缘出现锯齿
ctx.shadowColor = 'black'; // 边缘颜色
}
}
function reset() {
const oc = document.querySelector('canvas');
if (oc.getContext('2d')) {
const ctx = oc.getContext('2d');
ctx.clearRect(0, 0, oc.width, oc.height);
}
}
function down() {
const oc = document.querySelector('canvas');
var a = document.createElement('a');
a.download = 'sign.jpg';
a.href = oc.toDataURL('image/jpeg');
a.click();
}
</script>
</html>
抗锯齿处理参考: https://github.com/Louiszhai/canvas-draw