투케이2K

35. (html/css/javascript/jquery) canvas 캔버스 사용해 pc (피씨), mobile (모바일) 에서 전자 서명 기능 구현 - mouse , touch 본문

FrontEnd

35. (html/css/javascript/jquery) canvas 캔버스 사용해 pc (피씨), mobile (모바일) 에서 전자 서명 기능 구현 - mouse , touch

투케이2K 2021. 6. 19. 09:45

/* =========================== */

[ 개발 환경 설정 ]

개발 툴 : Edit++

개발 언어 : html, css, js, jquery

/* =========================== */

/* =========================== */

[소스 코드]

 

<!DOCTYPE HTML>
<!-- 자바스크립트 차단된 콘텐츠 자동 허용 실시 -->
<!-- saved from url=(0013)about:internet -->

<!-- 표시 언어 지정 -->
<html lang="ko">

<!-- 헤더 정의 부분 -->
<head>
    <title>HTML TEST</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">  
    

    <!-- 내부 CSS 스타일 지정 -->
    <style>
      /* 
      [CSS 요소 설명] 
      1. font-family : 폰트 표시 형태 스타일 지정
      2. width : 가로 크기 지정
      3. height : 세로 크기 지정
      4. margin : 마진 (외부) 여백 설정
      5. padding : 패딩 (내부) 여백 설정
      6. border : 테두리 (선) 표시 설정
      7. background : 배경 표시 설정
      8. overflow : 범위를 벗어난 콘텐츠 표시 여부 설정 (스크롤)
      9. float : 정렬 기준 설정
      10. div : 레이아웃 표시 블록
      11. position : 레이아웃 위치 정렬 설정
      12. display : 해당 div 영역을 표시 여부 설정
      */
                             
       
      /* html, body 영역 스타일 지정 */
      html, body{
         width : 100%;
         height : 100%;
         margin : 0;
         padding : 0;
         border : none;   
         
         /* 스크롤바 표시 지정 */
         overflow : auto;               
      }
      
      
      /* body 스크롤바 메인 스타일 지정 */
      body::-webkit-scrollbar {
         /* 스크롤바 너비 지정 */
         width: 10px;
         
         /* 스크롤바 배경 색상 지정 */
         background-color: #c1c1c1;
      }
      /* body 스크롤바 thumb 스타일 지정 */
      body::-webkit-scrollbar-thumb {               
         /* 스크롤바 thumb 색상 지정 */
         background-color: #444444;
      }
        
              
      #canvas_container {   
        width : 70%;
        height : 50%;
        margin : 0 auto;
        padding : 0;
        border : 1px solid #000000;
        /* background-color : #0000ff; */
               
        /* 컨테이너 배치 정렬 실시 */
        float : top;
        position : relative; 
        top : 10%;
        left : 0%;
         
        /* 마우스 커서 스타일 지정 */
        cursor : pointer;   

        /* 브라우저에서 화면 터치 시 파란박스 하이라이트 제거 */
        -webkit-tap-highlight-color : rgba(0,0,0,0);         

        /* div 테두리 영역 둥글게 설정 : 각 모서리 모두 동일 적용 : 일반 설정 */
        border-radius : 20px;
      }



      #url_container {   
        width : 70%;
        height : 10%;
        margin : 0 auto;
        padding : 0;
        border : none;
        background-color : #0000ff; 
               
        /* 컨테이너 배치 정렬 실시 */
        float : top;
        position : relative; 
        top : 13%;
        left : 0%;
         
        /* 마우스 커서 스타일 지정 */
        cursor : pointer;   

        /* 브라우저에서 화면 터치 시 파란박스 하이라이트 제거 */
        -webkit-tap-highlight-color : rgba(0,0,0,0);         

        /* div 테두리 영역 둥글게 설정 : 각 모서리 모두 동일 적용 : 일반 설정 */
        border-radius : 20px;

        /* display 설정 : p 태그 수직 정렬 */
		display : table;
      }




      #url_txt {   
        /* 텍스트 가로 정렬 지정 */
        text-align : center; 

        /* 텍스트 색상 지정 */
        color : #ffffff;

        /* 텍스트 굵기 지정 */
        font-weight : bold;
               
        /* 텍스트 사이즈 지정 */ 
        font-size : 150%;

        /* 텍스트 수직 정렬 실시 */
        display : table-cell;
        vertical-align : middle;
      }




      #picture_container {   
        width : 70%;
        height : 10%;
        margin : 0 auto;
        padding : 0;
        border : none;
        background-color : #339933; 
               
        /* 컨테이너 배치 정렬 실시 */
        float : top;
        position : relative; 
        top : 14%;
        left : 0%;
         
        /* 마우스 커서 스타일 지정 */
        cursor : pointer;   

        /* 브라우저에서 화면 터치 시 파란박스 하이라이트 제거 */
        -webkit-tap-highlight-color : rgba(0,0,0,0);         

        /* div 테두리 영역 둥글게 설정 : 각 모서리 모두 동일 적용 : 일반 설정 */
        border-radius : 20px;

        /* display 설정 : p 태그 수직 정렬 */
		display : table;
      }




      #picture_txt {   
        /* 텍스트 가로 정렬 지정 */
        text-align : center; 

        /* 텍스트 색상 지정 */
        color : #ffffff;

        /* 텍스트 굵기 지정 */
        font-weight : bold;
               
        /* 텍스트 사이즈 지정 */ 
        font-size : 150%;

        /* 텍스트 수직 정렬 실시 */
        display : table-cell;
        vertical-align : middle;
      }




      #delete_container {   
        width : 70%;
        height : 10%;
        margin : 0 auto;
        padding : 0;
        border : none;
        background-color : #ff00ff; 
               
        /* 컨테이너 배치 정렬 실시 */
        float : top;
        position : relative; 
        top : 15%;
        left : 0%;
         
        /* 마우스 커서 스타일 지정 */
        cursor : pointer;   

        /* 브라우저에서 화면 터치 시 파란박스 하이라이트 제거 */
        -webkit-tap-highlight-color : rgba(0,0,0,0);         

        /* div 테두리 영역 둥글게 설정 : 각 모서리 모두 동일 적용 : 일반 설정 */
        border-radius : 20px;

        /* display 설정 : p 태그 수직 정렬 */
		display : table;
      }




      #delete_txt {   
        /* 텍스트 가로 정렬 지정 */
        text-align : center; 

        /* 텍스트 색상 지정 */
        color : #ffffff;

        /* 텍스트 굵기 지정 */
        font-weight : bold;
               
        /* 텍스트 사이즈 지정 */ 
        font-size : 150%;

        /* 텍스트 수직 정렬 실시 */
        display : table-cell;
        vertical-align : middle;
      }   
                                                  
    </style>


    <!-- Jquery CDN 로드 : 항상 최신 버전 사용 -->
    <script  src="https://code.jquery.com/jquery-latest.min.js"></script>


    <!-- 내부 JS 지정 -->
    <script>

       /*
       [JS 요약 설명]
       1. window.onload : 웹 브라우저 로딩 완료 상태를 확인합니다
       2. canvas[0].getContext("2d") : 캔버스 오브젝트를 얻어옵니다
       3. canvas[0].height = div.height(); : 부모 div 크기만큼 영역을 생성합니다
       4. canvas.on("mousedown", pcDraw); : 이벤트를 등록합니다
       5. 참고 : pc 에서는 마우스로 처리, 모바일에서는 터치로 처리해야합니다       
       */


      
       

       /* [전역 변수 선언 부분] */
       var canvas;
       var div;

       var ctx;
       var drawble = false; //플래그값 설정 (그리기 종료)





       /* [html 최초 로드 및 이벤트 상시 대기 실시] */ 
       $(window).load(function(){
          console.log("");
          console.log("[window onload] : [start]");
          console.log("");

          // [초기 전역 변수 객체 등록 실시]
          canvas = $("#canvas");
          div = $("#canvas_container");

          ctx = canvas[0].getContext("2d"); //캔버스 오브젝트 가져온다          

          // [이벤트 등록 함수 호출]
          init();

          // [화면 조절 함수 호출]
          canvasResize();
       });





       /* [이벤트 등록 함수] */
       function init(){
          console.log("");
          console.log("[init] : [start]");
          console.log("");

          //캔버스 사이즈 조절
          $(window).on("resize", canvasResize);

          //PC 이벤트 등록
          canvas.on("mousedown", pcDraw);
          canvas.on("mousemove", pcDraw);
          canvas.on("mouseup", pcDraw);
          canvas.on("mouseout", pcDraw);
 
          //모바일 이벤트 등록
          canvas.on("touchstart", mobileDraw);
          canvas.on("touchend", mobileDraw);
          canvas.on("touchcancel", mobileDraw);
          canvas.on("touchmove", mobileDraw);

          //버튼 클릭 및 이미지 저장 등록
       };





       /* [화면 조절 함수] */
       function canvasResize(){
          console.log("");
          console.log("[canvasResize] : [start]");
          console.log("");

          //캔버스 사이즈 조절
          canvas[0].height = div.height();
          canvas[0].width = div.width();
       };





       /* [PC 그리기 이벤트 처리] */
       function pcDraw(evt){
          console.log("");
          console.log("[pcDraw] : [start]");
          console.log("");
          switch(evt.type){
            case "mousedown" : {
               BodyScrollDisAble(); //body 스크롤 정지
               drawble = true;
               ctx.beginPath();
               ctx.moveTo(getPcPosition(evt).X, getPcPosition(evt).Y);               
            }
            break;

            case "mousemove" : {
               if(drawble){
                  ctx.lineTo(getPcPosition(evt).X, getPcPosition(evt).Y);
                  ctx.stroke();
               }
            }
            break;

            case "mouseup" :
            case "mouseout" : {
               BodyScrollDisAble(); //body 스크롤 허용
               drawble = false;
               ctx.closePath();
            }
            break;
         }
       };

       function getPcPosition(evt){          
          var x = evt.pageX - canvas.offset().left;
          var y = evt.pageY - canvas.offset().top;
          return {X:x, Y:y};
       };





       /* [모바일 그리기 이벤트 처리] */
       function mobileDraw(evt){
          console.log("");
          console.log("[mobileDraw] : [start]");
          console.log("");

          switch(evt.type){
            case "touchstart" : {
               BodyScrollDisAble(); //body 스크롤 정지
               drawble = true;
               ctx.beginPath();
               ctx.moveTo(getMobilePosition(evt).X, getMobilePosition(evt).Y);
            }
            break;

            case "touchmove" : {
               if(drawble){
                  // 스크롤 및 이동 이벤트 중지
                  evt.preventDefault();
                  ctx.lineTo(getMobilePosition(evt).X, getMobilePosition(evt).Y);
                  ctx.stroke();
               }
            }
            break;

            case "touchend" :
            case "touchcancel" : {
               BodyScrollDisAble(); //body 스크롤 허용
               drawble = false;
               ctx.closePath();
            }
            break;
         }
       };

       function getMobilePosition(evt){
          var x = evt.originalEvent.changedTouches[0].pageX - canvas.offset().left;
          var y = evt.originalEvent.changedTouches[0].pageY - canvas.offset().top;
          return {X:x, Y:y};
       }; 





       /* [body 영역 스크롤 관리 부분] */
       function BodyScrollDisAble(){
          console.log("");
          console.log("[BodyScrollDisAble] : [start]");
          console.log("");         

          document.body.style.overflow = "hidden"; //스크롤 막음
       };
       function BodyScrollAble(){  
          console.log("");
          console.log("[BodyScrollAble] : [start]");
          console.log("");        

          document.body.style.overflow = "auto"; //스크롤 허용
       };





       /* [url 저장 부분] */
       function saveUrl(){
          console.log("");
          console.log("[saveUrl] : [start]");
          console.log(""); 

          console.log("");
          console.log("[saveUrl] : [url] : " + canvas[0].toDataURL()); //데이터베이스에 저장
          console.log("");                         
       };




       /* [캔버스 지우기 부분] */
       function savePicture(){
          console.log("");
          console.log("[savePicture] : [start]");
          console.log(""); 

          // a 태그를 만들어서 다운로드를 만듭니다
          var link = document.createElement("a");

          // base64 데이터 링크
          link.href = canvas[0].toDataURL("image/png"); //로컬 pc 다운로드 이미지

          // 다운로드시 파일명 지정
          link.download = "image.png";

          // body에 추가
          document.body.appendChild(link);
          link.click();          

          // 다운로드용 a 태그는 다운로드가 끝나면 삭제
          document.body.removeChild(link);
       };




       /* [캔버스 지우기 부분] */
       function deleteCanvas(){
          console.log("");
          console.log("[deleteCanvas] : [start]");
          console.log(""); 
          canvasResize(); //캔버스 새로고침       
       }; 
       
    </script>

</head>


<body>

<!-- 캔버스 레이아웃 -->
<div id = "canvas_container">
   <canvas id = "canvas"></canvas>
</div>



<!-- url 저장 -->
<div id = "url_container" onclick = "saveUrl();">
   <p id = "url_txt">URL 저장</p>	
</div>



<!-- 그림 저장 -->
<div id = "picture_container" onclick = "savePicture();">
   <p id = "picture_txt">그림 저장</p>	
</div>



<!-- 사인 지우기 -->
<div id = "delete_container" onclick = "deleteCanvas();">
   <p id = "delete_txt">지우기</p>	
</div>

</body>

</html>

/* =========================== */

/* =========================== */

[결과 출력]

/* =========================== */

/* =========================== */

[요약 설명]

/*

[CSS 요소 설명]

1. font-family : 폰트 표시 형태 스타일 지정

2. width : 가로 크기 지정

3. height : 세로 크기 지정

4. margin : 마진 (외부) 여백 설정

5. padding : 패딩 (내부) 여백 설정

6. border : 테두리 (선) 표시 설정

7. background : 배경 표시 설정

8. overflow : 범위를 벗어난 콘텐츠 표시 여부 설정 (스크롤)

9. float : 정렬 기준 설정

10. div : 레이아웃 표시 블록

11. position : 레이아웃 위치 정렬 설정

12. display : 해당 div 영역을 표시 여부 설정

*/

/*

[JS 요약 설명]

1. window.onload : 웹 브라우저 로딩 완료 상태를 확인합니다

2. canvas[0].getContext("2d") : 캔버스 오브젝트를 얻어옵니다

3. canvas[0].height = div.height(); : 부모 div 크기만큼 영역을 생성합니다

4. canvas.on("mousedown", pcDraw); : 이벤트를 등록합니다

5. 참고 : pc 에서는 마우스로 처리, 모바일에서는 터치로 처리해야합니다

*/

/* =========================== */

/* =========================== */

[파일 첨부]

소스코드.txt
0.01MB

 

index2.html
0.01MB

/* =========================== */

반응형
Comments