덧. 팁을 좀 더 업그레이드했습니다. https://www.xetown.com/lakepark/526822 이하의 팁도 활용가능하지만, 서명을 여러 개 받거나, 필수뿐 아니라 선택사항으로도 설정하시려는 경우에는 위 링크의 팁을 활용하시는 게 적절합니다.
후원회원 가입 등의 페이지를 개발할 때가 있을 겁니다.
관건은 이용자로부터 서명(사인, 싸인)을 어떻게 받을 거냐는 거겠죠.
이용자한테 후원신청서를 출력해서 직접 서명한 다음에 팩스로 전송해달라는 사이트도 있더군요;;;
이 팁을 활용하면 PC에서든 모바일에서든 이용자가 직접 서명을 그려서 서버에 전달할 수가 있습니다.
게시판 모듈의 확장변수를 이용한 방법인데, 다양한 방식으로 응용이 가능하리라고 판단됩니다.
스케치북 스킨 기준으로 설명을 드리겠습니다.
1. 준비물 구하기
- 앞선 게시물 https://www.xetown.com/square/519687 에도 썼듯이, http://www.jqueryscript.net/other/Smooth-Signature-Pad-Plugin-with-jQuery-Html5-Canvas.html 로 갑니다.
- Download 받으세요.
- jquery.signaturepad.css 파일은 css 폴더에 저장해줍니다. (스케치북 스킨의 css 폴더를 말하는 거예요)
- numeric-1.2.6.min.js, bezier.js, jquery.signaturepad.js, js/json2.min.js 등의 파일은 js 폴더에 저장해줍니다. (마찬가지로 스케치북 스킨의 js 폴더)
- 그러면, 확장변수를 만들어보겠습니다.
2. 확장변수 만들기
- 게시판 관리 > 사용자 정의 > 추가로 들어가서 확장변수를 만듭니다.
- 여기서는 '사용자 정의 이름'을 signature로 한다고 가정하겠습니다.
- '입력항목 이름'은 원하시는 대로 하세요. 저는 그냥 '서명'이라고 했습니다.
- '입력형식'은 무엇으로 하든 관계가 없으니 가급적이면 그냥 내버려둡니다 ㅋ
- 서명은 필수일 테니 '필수항목'에선 '예'를 체크합니다.
- '설명'은 대강 이렇게 해보죠. '윗칸에 서명을 그려 넣어주세요.'
- '검색'은 '아니오'를 권장합니다.
- 그리고 반드시 그럴 필요는 없지만 signature 변수를 사용자 정의 목록에서 맨 마지막으로 해주세요. 제가 알려드리는 팁은 그걸 전제로 작성됩니다;;;
- 그럼, 슬슬 소스 수정을 시작해볼까요?
3. write_form.html 수정
- 스킨 폴더에서 write_form.html 파일을 꺼낸 뒤 수정을 시작합니다. 잘 찾아보시면 <table cond="count($extra_keys)" class="et_vars exForm bd_tb">이라는 부분이 있을 겁니다. 이게 바로 확장변수 입력하는 테이블이에요.
- 그 아래아래에 <tr loop="$extra_keys=>$key,$val"> 같은 태그가 있을 겁니다. 얘를 아래와 같이 수정해봅니다. 이렇게 하면 테이블은 서명 부분만 빼고 입력 폼을 띄우게 되겠죠?
<tr loop="$extra_keys=>$key,$val" cond="$val->eid!='signature'">
- 확장변수 입력 table 태그 뒤에 본격적으로 서명 부분 코딩을 시작합니다. 대략 아래와 같이 해보겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!-- // 서명 받기 --> <!--@ if ( $extra_keys [ count ( $extra_keys )]->eid== 'signature' )--> // 사용자 정의 목록의 맨 마지막이 signature 변수인 경우에 출력 {@ $i = count ( $extra_keys ) ;} // 목록 마지막에 있는 signature 변수의 키값을 간략하게 재정의 <load target= "css/jquery.signaturepad.css" /><load target= "js/numeric-1.2.6.min.js" /><load target= "js/bezier.js" /><load target= "js/jquery.signaturepad.js" /><load target= "js/json2.min.js" /> // 1번 항목의 준비물들을 불러옴 <div class = "sigPad" style= "width:296px; display:table; margin:0 auto;" > // 모바일 최소 가로사이즈(320px) - 확장변수 입력 화면의 padding값(12px*2) = 296px ... 그리고 가운데 정렬 <ul class = "sigNav" > <h3>{ $extra_keys [ $i ]->name}<em>*</em></h3> // 사용자 정의에서 설정한 '입력항목 이름' 출력 ... 서명은 필수이므로 * 표시를 조건없이 출력 <li class = "clearButton" ><a href= "#clear" >{ $lang ->reload}</a></li> // 서명 그리기 초기화를 위한 '새로고침' 링크 </ul> <div class = "sig sigWrapper" style= "height:100px;" > // 높이는 각자 원하는 대로 취향껏 <div class = "typed" ></div> // 에러 메시지가 뜨는 부분인데, XE에선 그닥 사용하는 일이 없긴 함 <canvas class = "pad" id= "cy_sig" width= "294" height= "100" ></canvas> // 서명 그려넣는 부분. 넓이는 위의 296px - border값(1px*2), 높이는 윗윗줄에서 설정한 값 <input type= "hidden" name= "extra_vars{$i}" id= "cy_sig_data" class = "output" value= "{$oDocument->getExtraEidValue($extra_keys[$i]->eid)}" > // canvas의 그림이 전달되는 입력폼. type이 hidden이므로 사용자에겐 표시 안 됨 </div> <p style= "margin-top:5px;text-align:center;font-size:11px;" >{ $extra_keys [ $i ]->desc}</p> // 사용자정의 설명 부분인데 이것도 각자 취향껏 </div> <!--@ end --> |
- 그 다음엔 윗 부분 아래쯤에 '서명js의 옵션 설정', '그려진 이미지의 문자열 전달 처리', 그리고 (게시물 수정시에 불러올) '문자열의 이미지 처리'를 위해 다음과 같은 스크립트 코드를 넣어줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <!-- // 서명 옵션 설정 및 서명 이미지값 문자열 전달 처리 --> <script> jQuery(document).ready( function (){ jQuery( '.sigPad' ).signaturePad({ // 기본 옵션을 설정하는데, 자세한 설명은 위의 링크 페이지를 참조해보세요^^ drawOnly: true , drawBezierCurves: true , lineTop:90 // 이건 canvas에 깔아놓는 기본 밑줄 같은 겁니다. 숫자는 top값을 의미하죠 }); }); function toDataURL(){ // 이 함수를 통해 canvas의 그림이 문자열로 변환됩니다. 해당 문자열은 확장변수의 입력값이 되는 거죠ㅋ var canvas = document.getElementById( 'cy_sig' ), cv_data = document.getElementById( 'cy_sig_data' ); if (cv_data.value != '' ){ // 여기에 조건을 주긴 했는데, 제가 무슨 정신으로 이런 조건을 줬는지는 잘 기억이 안 나네요. 어쨌든 잘 작동할 겁니다;; cv_data.value = canvas.toDataURL(); } else { return false ; } } </script> <!-- // 서명 수정시 기존 서명 출력 처리 --> <script cond= "$oDocument->getExtraEidValue('signature')" > // 수정 화면에서 서명이 기입력되어 있을 때만 작동하는 스크립트라는 뜻이겠죠. if (window.addEventListener) { window.addEventListener( 'load' , InitEvent, false ); } function InitEvent(){ var canvas = document.getElementById( 'cy_sig' ), context = canvas.getContext( '2d' ), cv_data = document.getElementById( 'cy_sig_data' ); var image = new Image(); image.src = "{$oDocument->getExtraEidValue('signature')}" ; // 서명 폼의 문자열 값으로 이미지 url을 만들어줍니다. image.onload = function (){ // 해당 이미지는 캔버스에 그림으로 그려지게 되죠. context.drawImage(image,0,0); cv_data.value = canvas.toDataURL(); } } </script> |
- 마지막으로 하나 더 남았습니다. 위의 toDataURL 함수를 실행시켜줘야 하니까요. 파일 상단 부분에 보면 <form action="./" method="post" onsubmit="return procFilter(this, window.insert)" class="bd_wrt bd_wrt_main clear">라는 곳이 있을 겁니다. 얘를 다음과 같이 바꿔주세요.
<form action="./" method="post" onsubmit="<!--@if($extra_keys[count($extra_keys)]->eid=='signature')-->toDataURL();<!--@end-->return procFilter(this, window.insert)" class="bd_wrt bd_wrt_main clear">
- 이렇게 해야 글 등록시에 서명 입력 부분이 문자열로 변환돼서 서버에 전달이 됩니다. 그림이 안 그려지면요? 아까 숨겨놨던 인풋 박스에 아무런 값도 전달이 안 되면서 "서명 값은 필수입니다." 같은 경고창이 뜨겠죠.
- 이렇게 서명 입력 화면을 손봤으니, 이제는 출력 화면 차례겠네요.
4. _read.html 수정
- 주지하시듯, 게시물 본문은 _read.html. 따라서 확장변수로서 signature도 여기서 일람해볼 수 있습니다. 다만, 서버로 전달된 복잡한 문자열을 다른 확장변수처럼 바로 출력할 순 없겠죠.
- 여기서 <caption class="blind">Extra Form</caption>라는 구문이 들어간 두 개의 table을 볼 수 있을 겁니다. '스킨 설정 > 본문 일반 설정 > 확장변수 위치'가 '본문 안에(기본)'인 경우엔 아래쪽 table, '제목 아래'인 경우엔 윗쪽 table이 될 겁니다.
- 이 테이블'들'에 td 태그 부분이 있습니다. 대개는 이렇게 되어 있죠. 평점 매기는 게시판을 구분 하기 위한 코드들인 거 같네요.
<td cond="$val->eid!='rating'">{$val->getValueHTML()}</td>
<td cond="$val->eid=='rating'" class="rating"><span class="starRating" title="{$val->getValueHTML()}{$lang->score}"><span style="width:{$val->getValueHTML()*10}%">{$val->getValueHTML()}</span></span></td>
- 위의 코드'들'을 다음과 같이 바꿔줍니다. 네, 바로 두 번째 줄이 핵심입니다. 서명 변수에 한해서 이미지로 불러오는 거죠. 입력되어 있는 값은 이미지의 dataURL이니까요ㅎㅎ
1 2 3 | <td cond= "$val->eid!='rating'&&$val->eid!='signature'" >{ $val ->getValueHTML()}</td> <td cond= "$val->eid!='rating'&&$val->eid=='signature'" ><img src= "{$val->getValueHTML()}" /></td> <td cond= "$val->eid=='rating'&&$val->eid!='signature'" class = "rating" ><span class = "starRating" title= "{$val->getValueHTML()}{$lang->score}" ><span style= "width:{$val->getValueHTML()*10}%" >{ $val ->getValueHTML()}</span></span></td> |
- 혹시 모르니 두 군데 테이블 모두 위와 같이 바꿔주시는 게 좋을 것 같습니다. 강력 권장.
... 이상입니다.
혹시 버그가 있을지 모르겠지만, 제 기억으로는 이 정도 선이었던 거 같아요;;;
유용하게 쓰시면 좋겠네요 :)
여러분들도 좋은 정보 있으면 많이 알려주세요~~