본문 바로가기
javascript

HTML, CSS, JS , 캔버스로 서명 패드 만들기

by it-square 2021. 12. 28.
반응형

안녕, 오늘 나는 매우 멋진 것을 공유할 수 있어.

사용자의 서명이나 도면을 수집해야 할 경우에 대비하여 프로그램에 추가할 수 있는 서명 패드를 만드는 방법을 알려드리겠습니다.

또한 서명 패드에서 서버를 보낼 수 있는 이미지를 만드는 방법도 알려드리겠습니다.

준비됐나요? 를 시작하겠습니다.

 

먼저 hour page의 HTML 구조를 만들고 app.js와 app.css를 index.html 페이지에 연결해보자.

<!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>Singature Pad</title>
  <link rel="stylesheet" href="app.css">
    </head>
<body>
      <form class="signature-pad-form" action="#" method="POST">
            <h1>Important Contract</h1>
    <p>Important contract description</p>
    <p><b>Signature</b></p>
          <canvas height="100" width="300" class="signature-pad"></canvas>
    <p><a href="#" class="clear-button">Clear</a></p>
          <button class="submit-button" type="submit">SUBMIT</button>
  </form>
  <script src="app.js"></script>
</body>
</html>

이제 app.css 파일에 css를 추가하여 시그니처 패드처럼 보이도록 하겠습니다.

:root {
    --primary-color: #000;
}
body {
    font-family: Arial, Helvetica, sans-serif;
    line-height: 1.4;
    padding: 1rem;
}
.signature-pad-form {
    max-width: 300px;
    margin: 0 auto;
}
.signature-pad {
    cursor: url(pen.png) 1 26, pointer;
    border: 2px solid var(--primary-color);
    border-radius: 4px;
}
.clear-button {
    color: var(--primary-color);
}
.submit-button {
    width: 100%;
      background-color: var(--primary-color);
    border: none;
    padding: 0.5rem 1rem;
    color: #fff;
    cursor: pointer;
    margin-top: 2rem;
}
@media (pointer: coarse) {
    body {
          overflow: hidden; /* Needed to prevent the vertical scroll on touch devices */
    }
}

좋아, 이제 구조와 스타일이 정해졌으니 재미있는 일을 해보자:)

 

우리는 이제 app.js에서 코드 작성을 시작할 수 있다.

먼저 서명 패드를 지울 수 있는 양식, 캔버스 및 단추에 대한 몇 가지 상수를 저장하려고 합니다.

const canvas = document.querySelector('canvas');
const form = document.querySelector('.signature-pad-form');
const clearButton = document.querySelector('.clear-button');

그러면 곧 필요할 캔버스 컨텍스트를 다른 상수에서 저장해 봅시다. 이 경우 서명이 2d이므로 2d 컨텍스트만 있으면 됩니다.

const ctx = canvas.getContext('2d');
 

마지막으로 쓰기 모드를 설정 및 해제할 수 있는 변수를 몇 개 만들어 보겠습니다.

let writingMode = false;

완벽해!

다음 단계로 이벤트 수신기가 패드와 상호 작용하도록 설정할 수 있습니다. 우리는 포인터다운, 포인터업, 포인터모브의 소리를 들어야 할 것이다.

포인터다운은 쓰기 모드를 true로 설정하는 데 사용되고 포인터업은 쓰기 모드를 false로 설정하는 데 사용됩니다.

 
canvas.addEventListener('pointerdown', handlePointerDown, {passive: true});
canvas.addEventListener('pointerup', handlePointerUp, {passive: true});
canvas.addEventListener('pointermove', handlePointerMove, {passive: true});

이제 핸들러를 구현해 보겠습니다.

handlePointerDown

const handlePointerDown = (event) => {
    writingMode = true;
    ctx.beginPath();
    const [positionX, positionY] = getCursorPosition(event);
    ctx.moveTo(positionX, positionY);
}

handlePointerUp

 
const handlePointerUp = () => {
    writingMode = false;
}

handlePointerMove

const handlePointerMove = (event) => {
    if (!writingMode) return
    const [positionX, positionY] = getCursorPosition(event);
    ctx.lineTo(positionX, positionY);
    ctx.stroke();
}

여기서 getCursorPosition은 다음과 같습니다.

const getCursorPosition = (event) => {
    positionX = event.clientX - event.target.getBoundingClientRect().x;
    positionY = event.clientY - event.target.getBoundingClientRect().y;
    return [positionX, positionY];
}
 

그런 다음 캔버스 컨텍스트에 몇 가지 속성을 설정하여 도면 선의 스타일을 지정합니다.

ctx.lineWidth = 3;
ctx.lineJoin = ctx.lineCap = 'round';

거의 다 왔습니다, 마지막으로 추가할 것은 캔버스를 지우는 기능과 양식을 제출하는 기능입니다.

form.addEventListener('submit', (event) => {
    event.preventDefault();
    const imageURL = canvas.toDataURL();
    const image = document.createElement('img');
    image.src = imageURL;
    image.height = canvas.height;
    image.width = canvas.width;
    image.style.display = 'block';
    form.appendChild(image);
    clearPad();
})
const clearPad = () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
}
clearButton.addEventListener('click', (event) => {
    event.preventDefault();
    clearPad();
})

바로 그거야! 최종 결과는 이렇게 나와야 돼.

 

읽어주셔서 감사하고 다음 기사에서 뵙겠습니다:) 좋은 하루 보내시고 행복한 코딩!

댓글