我需要一个可以转换为图像的签名板。 我开始使用 VMAJSTER 的代码。
我删除了羽毛并添加了图像创建选项。
现在我遇到了问题,当书写(当鼠标按下时)并离开你仍在书写的区域时,当鼠标松开时。如何在离开画布时添加书写停止?
// SOURCE https://codepen.io/vmajster/pen/zYxowrv
// by VMAJSTER
(function() {
/*
To do:
Implement a more natural dragging movements with the formula from this script:
https://github.com/nashvail/SmootherTrello/blob/master/content.js
Read more at:
https://uxdesign.cc/how-to-fix-dragging-animation-in-ui-with-simple-math-4bbc10deccf7
*/
var devicePixelRatio = window.devicePixelRatio || 1;
var main = document.getElementById("main");
var canvas = document.getElementById("paint");
var ctx = canvas.getContext("2d");
var sketch = document.getElementById("sketch");
var sketch_style = getComputedStyle(sketch);
var inputType = "mouse";
canvas.width = parseInt(sketch_style.getPropertyValue("width"), 10);
canvas.height = parseInt(sketch_style.getPropertyValue("height"), 10);
// Creating a tmp canvas
var tmp_canvas = document.createElement("canvas");
var tmp_ctx = tmp_canvas.getContext("2d");
tmp_canvas.id = "tmp_canvas";
tmp_canvas.width = canvas.width;
tmp_canvas.height = canvas.height;
sketch.appendChild(tmp_canvas);
var mouse = {
x: 0,
y: 0
};
// Pen Points
var ppts = [];
/* Mouse Capturing Work */
tmp_canvas.addEventListener("mousemove", function(e) {
mouse.x = typeof e.offsetX !== "undefined" ? e.offsetX : e.layerX;
mouse.y = typeof e.offsetY !== "undefined" ? e.offsetY : e.layerY;
e.stopPropagation();
e.preventDefault();
return false;
}, false);
/* Drawing */
tmp_ctx.lineWidth = 1.5 * devicePixelRatio; /* Size of the drawn line * devicePixelRatio */
tmp_ctx.lineJoin = "round";
tmp_ctx.lineCap = "round";
tmp_ctx.strokeStyle = "rgba(0, 0, 0, 0.8)";
tmp_ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
tmp_canvas.addEventListener("mousedown", function(e) {
tmp_canvas.addEventListener("mousemove", onPaint, false);
mouse.x = typeof e.offsetX !== "undefined" ? e.offsetX : e.layerX;
mouse.y = typeof e.offsetY !== "undefined" ? e.offsetY : e.layerY;
ppts.push({
x: mouse.x,
y: mouse.y
});
onPaint(e);
}, false);
tmp_canvas.addEventListener("mouseup", function() {
if (inputType === "touch") {
}
else {
inputType = "mouse";
}
tmp_canvas.removeEventListener("mousemove", onPaint, false);
// Writing to real canvas now
ctx.drawImage(tmp_canvas, 0, 0);
// Clearing tmp canvas
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
// Emptying up Pen Points
ppts = [];
}, false);
var onPaint = function(e) {
// Saving all the points in an array
ppts.push({
x: mouse.x,
y: mouse.y
});
if (ppts.length < 3) {
var b = ppts[0];
tmp_ctx.beginPath();
tmp_ctx.arc(b.x, b.y, tmp_ctx.lineWidth / 2, 0, Math.PI * 2, !0);
tmp_ctx.fill();
tmp_ctx.closePath();
e.preventDefault();
e.stopPropagation();
return false;
}
// Tmp canvas is always cleared up before drawing.
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
tmp_ctx.beginPath();
tmp_ctx.moveTo(ppts[0].x, ppts[0].y);
for (var i = 1; i < ppts.length - 2; i++) {
var c = (ppts[i].x + ppts[i + 1].x) / 2;
var d = (ppts[i].y + ppts[i + 1].y) / 2;
tmp_ctx.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d);
}
// For the last 2 points
tmp_ctx.quadraticCurveTo(ppts[i].x, ppts[i].y, ppts[i + 1].x, ppts[i + 1].y);
tmp_ctx.stroke();
e.preventDefault();
e.stopPropagation();
return false;
};
// Clear canvas
document.getElementById("clear").onmousedown = document.getElementById("clear").ontouchstart = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
};
// Save canvas
document.getElementById("create").onmousedown = document.getElementById("create").ontouchstart = function() {
if(!!document.getElementById("signature") === false) {
var sig_image = document.createElement('img');
sig_image.id = 'signature';
document.getElementById("actions").after(sig_image);
}
else {
var sig_image = document.getElementById("signature");
}
var paint = document.getElementById("paint");
var p_image = paint.toDataURL("image/png");
sig_image.src = p_image;
};
function touchHandler(event) {
var touch = event.changedTouches[0];
inputType = "touch";
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent({ touchstart: "mousedown", touchmove: "mousemove", touchend: "mouseup" }[event.type], true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
touch.target.dispatchEvent(simulatedEvent);
event.preventDefault();
event.stopPropagation();
return false;
}
main.addEventListener("touchstart", touchHandler, true);
main.addEventListener("touchmove", touchHandler, true);
main.addEventListener("touchend", touchHandler, true);
/*
main.addEventListener("touchstart", function(e) {
e.preventDefault();
e.stopPropagation();
return false;
}, false);
*/
})();
:root {
background-color: #F3F3F3;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
-moz-tap-highlight-color: transparent;
-ms-tap-highlight-color: transparent;
-o-tap-highlight-color: transparent;
tap-highlight-color: transparent;
}
*,
:before,
:after {
-webkit-box-sizing: inherit;
-moz-box-sizing: inherit;
-ms-box-sizing: inherit;
-o-box-sizing: inherit;
box-sizing: inherit;
}
body {
margin: 0;
padding: 0;
}
#sketch {
left: 0;
right: 0;
bottom: 0;
top: 0;
display: block;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
contain: strict;
}
canvas {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
display: block;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
contain: strict;
}
canvas, #clear {
-webkit-touch-action: manipulation;
-moz-touch-action: manipulation;
-ms-touch-action: manipulation;
-o-touch-action: manipulation;
touch-action: manipulation;
}
#main {
background: #ccc;
padding: 20px;
}
#sketch {
display: block;
position: relative;
border: 1px solid #000;
width: 500px;
height: 180px;
background: #fff;
margin: 0 auto;
}
#sketch:before {
position: absolute;
display: block;
height: 1px;
background: transparent;
border-bottom: 1px solid #aaa;
padding: 20px;
bottom: 40px;
left: 20px;
right: 20px;
top: auto;
content: "";
}
#sketch_redzone {
display: block;
box-sizing: border-box;
width: 100%;
height: 100%;
border: 20px solid rgba(255,0,0,0.1);
}
#actions {
display: block;
text-align: center;
}
#signature {
display: block;
margin: 0 auto;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Signature</title>
</head>
<body>
<main id="main" role="main" tabindex="0">
<div id="sketch">
<div id="sketch_redzone"></div>
<canvas id="paint"></canvas>
</div>
<div id="actions">
<button type="button" id="clear">Clear</button>
<button type="button" id="create">Create PNG</button>
</div>
</main>
</body>
</html>
让它工作,但我不确定这是否是最好的方法。 我将“mouseup”的事件监听器函数的操作存储到预定义函数中,并在“mouseleave”时触发该函数。
如果有更好的方法请评论,否则我认为还可以
function stopDrawing() {
if (inputType === "touch") {
}
else {
inputType = "mouse";
}
tmp_canvas.removeEventListener("mousemove", onPaint, false);
// Writing to real canvas now
ctx.drawImage(tmp_canvas, 0, 0);
// Clearing tmp canvas
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
// Emptying up Pen Points
ppts = [];
}
tmp_canvas.addEventListener("mouseup", function() {
stopDrawing();
}, false);
tmp_canvas.addEventListener("mouseleave", function(e) {
stopDrawing();
}, false);