웹브라우저에서 서명받는 프로그램 (html + css + javascript)
2022.03.02
PC,Mobile 웹 브라우저에서 서명을 받아 저장 가능한 프로그램 설명
인터페이스
HTML 코드
서명을 위한 캔버스와 동작을 위한 버튼
<!-- 서명 공간 -->
<div>
<h3>서명1</h3>
<div class="canvas-draw-box">
<div class="canvas-draw-base" data-id="canvas_name1"></div>
<div class="canvas-draw-pad-box">
<canvas id="canvas_name1" class="canvas-draw-pad">1. 사용중인 브라우저에서 지원하지 못합니다.</canvas>
<div>
<button onClick="javascript:save('canvas_name1')">save</button>
<button onClick="javascript:down('canvas_name1')">download</button>
<button onClick="javascript:del('canvas_name1')">clear</button>
<button onClick="javascript:done('canvas_name1')">done</button>
</div>
</div>
</div>
</div>
<div>
<h3>서명2</h3>
<div class="canvas-draw-box">
<div class="canvas-draw-base" data-id="canvas_name2"></div>
<div class="canvas-draw-pad-box">
<canvas id="canvas_name2" class="canvas-draw-pad">2. 사용중인 브라우저에서 지원하지 못합니다.</canvas>
<div>
<button onClick="javascript:save('canvas_name2')">save</button>
<button onClick="javascript:down('canvas_name2')">download</button>
<button onClick="javascript:del('canvas_name2')">clear</button>
<button onClick="javascript:done('canvas_name2')">done</button>
</div>
</div>
</div>
</div>
CSS 코드
서명부분 캔버스 스타일 지정, 배경이미지는 필요에 따라서 사용하자.
.canvas-draw-box {
position: relative;
}
.canvas-draw-base {
border:1px solid black;
width: 100px;
height: 100px;
background-image: url(서명배경이미지);
background-position-x: center;
background-position-y: center;
background-size: contain;
background-repeat-x: no-repeat;
background-repeat-y: no-repeat;
background-attachment: initial;
background-origin: initial;
background-clip: initial;
background-color: initial;
}
.canvas-draw-pad-box {
position: absolute;
z-index: 9999;
top: 0;
background-color: white;
display: none;
}
.canvas-draw-pad {
border:1px solid black;
}
JS 코드
캔버스에 마우스이동에 따라 선을 그려서 서명을 생성(그림그리기)
var _CANVAS = new function () {
// 서명 : 이곳을 터치하세요.
let baseSign = "배경이미지";
this.start = function (_canvas, _width, _height) {
let isDrawing = false;
let x = 0;
let y = 0;
const drawCanvas = document.getElementById(_canvas);
const context = drawCanvas.getContext('2d');
drawCanvas.width = _width;
drawCanvas.style.width = _width + "px";
drawCanvas.height = _height;
drawCanvas.style.height = _height + "px";
drawCanvas.addEventListener('mousedown', e => {
x = e.offsetX;
y = e.offsetY;
isDrawing = true;
});
drawCanvas.addEventListener('mousemove', e => {
if (isDrawing === true) {
this.drawLine(context, x, y, e.offsetX, e.offsetY);
x = e.offsetX;
y = e.offsetY;
}
});
window.addEventListener('mouseup', e => {
if (isDrawing === true) {
this.drawLine(context, x, y, e.offsetX, e.offsetY);
x = 0;
y = 0;
isDrawing = false;
}
});
drawCanvas.addEventListener('touchstart', e => {
isDrawing = true;
context.beginPath();
context.moveTo(getPosition(e).X, getPosition(e).Y);
x = getPosition(e).X;
y = getPosition(e).Y;
});
drawCanvas.addEventListener('touchmove', e => {
if (isDrawing === true) {
e.preventDefault();
this.drawLine(context, x, y, getPosition(e).X, getPosition(e).Y);
x = getPosition(e).X;
y = getPosition(e).Y;
}
});
drawCanvas.addEventListener('touchend', e => {
context.closePath();
x = 0;
y = 0;
isDrawing = false;
});
function getPosition(e) {
// canvas의 실제 위치 (position:absolute)
var drawCanvasPos = drawCanvas.getBoundingClientRect();
return {
X: e.changedTouches[0].pageX - drawCanvas.offsetLeft - drawCanvasPos.left,
Y: e.changedTouches[0].pageY - drawCanvas.offsetTop - drawCanvasPos.top
}
}
}
this.drawLine = function (context, x1, y1, x2, y2) {
context.beginPath();
context.strokeStyle = 'black';
context.lineWidth = 1;
context.moveTo(x1, y1);
context.lineTo(x2, y2);
context.stroke();
context.closePath();
}
this.getCanvas = function (_canvas) {
const drawCanvas = document.getElementById(_canvas);
var data = drawCanvas.toDataURL("image/png");
return data;
}
this.clearCanvas = function (_canvas) {
const drawCanvas = document.getElementById(_canvas);
drawCanvas.getContext("2d").clearRect(0, 0, drawCanvas.width, drawCanvas.height);
}
this.downCanvas = function (_canvas) {
var link = document.createElement('a');
link.href = this.getCanvas(_canvas);
link.download = _canvas + "-" + new Date().getTime() + ".png";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
this.doneCanvas = function (_canvas) {
const drawCanvas = document.getElementById(_canvas);
var data = this.getCanvas(_canvas);
this.clearCanvas(_canvas);
var blankImage = this.getCanvas(_canvas);
if (data != blankImage) {
drawCanvas.parentNode.previousElementSibling.style.backgroundImage = "url('" + data + "')";
} else {
drawCanvas.parentNode.previousElementSibling.style.backgroundImage = "url('" + baseSign + "')";
}
drawCanvas.parentElement.style.display = "none";
}
// 이전 이미지를 가져와서 canvas에 삽입
this.setPreImage = function (_canvas) {
const drawCanvas = document.getElementById(_canvas);
const context = drawCanvas.getContext('2d');
var preImage = drawCanvas.parentNode.previousElementSibling.style.backgroundImage;
preImage = preImage.replace(/(url\(|\)|")/g, '');
if (preImage != baseSign) {
var img = new Image();
img.src = preImage;
img.onload = function () {
context.drawImage(img, 0, 0);
}
}
}
};
$(function () {
_CANVAS.start("canvas_name1", 300, 300);
_CANVAS.start("canvas_name2", 300, 300);
});
function save(_canvas) {
var data = _CANVAS.getCanvas(_canvas);
console.log("data is : " + data);
}
function del(_canvas) {
_CANVAS.clearCanvas(_canvas);
}
function down(_canvas) {
_CANVAS.downCanvas(_canvas);
}
function done(_canvas) {
_CANVAS.doneCanvas(_canvas);
}
$("body").delegate(".canvas-draw-base", "click", function () {
var _canvas = $(this).data("id");
$("canvas#" + _canvas).parents(".canvas-draw-pad-box").show();
//$(this).siblings(".canvas-draw-pad-box").show();
// 이전 이미지를 가져와서 canvas에 삽입
_CANVAS.setPreImage(_canvas);
});