728x90

요즘 비대면 결제 부터 많은 계약서들이 온라인으로 진행이 되고 있다. 그 중 빠질 수 없는 부분이 동의를 하고 서명하는 부분인데 이 서명란을 모바일 , pc 마우스나 터치로 그리고 이미지로 저장 받는 로직이 필요할때가 많다. 

 

서명을 그리는 부분은 canvas 태그와 스크립트로 가능하고 파일을 저장하는 로직은 php 코드에서 진행한다. 이때 유의할 점은 스크롤이 생기면 캔버스가 자리를 제대로 인식하지 않기 때문에 서명 페이지는 다른 글이 나오는 중간에 넣기 보다 새창을 띄워서 서명을 따로 받고 저장 된 이미지를 본문에 보여주는 식의 코드가 오류가 없다. 

 

아래는 서명을 받는 스크립트와 이미지로 저장하는 로직 까지 같이 메모해 본다. 

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    canvas {
      border: 2px solid #000;
			touch-action: none;
    }
  </style>
</head>
<body>
  <canvas id="drawCanvas" width="300" height="200"></canvas>
  <button id="saveButton">Save Image</button>

  <script>
    const canvas = document.getElementById('drawCanvas');
    const context = canvas.getContext('2d');

    let isDrawing = false;

    function startDrawing(e) {
			e.preventDefault(); // 모바일에서 스크롤 방지
      isDrawing = true;
      draw(e);
    }

    function stopDrawing() {
      isDrawing = false;
      context.beginPath();
    }

    function draw(e) {
      if (!isDrawing) return;

      context.lineWidth = 2;
      context.lineCap = 'round';
      context.strokeStyle = '#000';

			// 모바일 터치 이벤트 처리
			if (e.touches) {
				context.lineTo(e.touches[0].clientX - canvas.offsetLeft, e.touches[0].clientY - canvas.offsetTop);
			} else {
				// 마우스 이벤트 처리
				context.lineTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
			}

			context.stroke();
			context.beginPath();

			// 모바일 터치 이벤트 처리
			if (e.touches) {
				context.moveTo(e.touches[0].clientX - canvas.offsetLeft, e.touches[0].clientY - canvas.offsetTop);
			} else {
				// 마우스 이벤트 처리
				context.moveTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
			}
			/*
      context.lineTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
      context.stroke();
      context.beginPath();
      context.moveTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
			*/
    }

    function saveImage() {
      const dataUrl = canvas.toDataURL(); // Canvas의 데이터 URL을 얻습니다.

      // PHP로 데이터 전송
      const xhr = new XMLHttpRequest();
      xhr.open('POST', 'save_image.php', true);
      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
          alert(xhr.responseText); // 서버에서의 응답 처리 (예: 성공 메시지)
        }
      };
      xhr.send('image=' + encodeURIComponent(dataUrl));
    }

    canvas.addEventListener('mousedown', startDrawing);
    canvas.addEventListener('mousemove', draw);
    canvas.addEventListener('mouseup', stopDrawing);
    canvas.addEventListener('mouseout', stopDrawing);
    canvas.addEventListener('touchstart', startDrawing);
    canvas.addEventListener('touchmove', function (e) {
      e.preventDefault();
      draw(e.touches[0]);
    });
    canvas.addEventListener('touchend', stopDrawing);

    document.getElementById('saveButton').addEventListener('click', saveImage);
  </script>
</body>
</html>

 

이미지 저장 로직

<?php
if (isset($_POST['image'])) {
    $dataUrl = $_POST['image'];

    // 데이터 URL에서 base64 부분을 제거합니다.
    $data = explode(',', $dataUrl);
    $base64Data = $data[1];

    // base64 디코딩
    $imageData = base64_decode($base64Data);

    // 파일 경로 및 파일 이름 설정
    $filePath = '../uploads/';
    $fileName = uniqid('image_') . '.png';
    $fileFullPath = $filePath . $fileName;

    // 파일 저장
    file_put_contents($fileFullPath, $imageData);

    // 파일 경로 또는 파일 이름을 클라이언트에게 전달 (예: 성공 메시지)
    echo '이미지가 성공적으로 저장되었습니다. 파일 경로: ' . $fileFullPath;
} else {
    // 이미지 데이터가 전송되지 않았을 경우 에러 메시지
    echo '이미지 데이터가 전송되지 않았습니다.';
}
?>
728x90

+ Recent posts