덧. 팁을 좀 더 업그레이드했습니다. 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 태그 뒤에 본격적으로 서명 부분 코딩을 시작합니다. 대략 아래와 같이 해보겠습니다.
<!--// 서명 받기 --> <!--@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의 옵션 설정', '그려진 이미지의 문자열 전달 처리', 그리고 (게시물 수정시에 불러올) '문자열의 이미지 처리'를 위해 다음과 같은 스크립트 코드를 넣어줍니다.
<!--// 서명 옵션 설정 및 서명 이미지값 문자열 전달 처리 --> <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이니까요ㅎㅎ
<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>
- 혹시 모르니 두 군데 테이블 모두 위와 같이 바꿔주시는 게 좋을 것 같습니다. 강력 권장.
... 이상입니다.
혹시 버그가 있을지 모르겠지만, 제 기억으로는 이 정도 선이었던 거 같아요;;;
유용하게 쓰시면 좋겠네요 :)
여러분들도 좋은 정보 있으면 많이 알려주세요~~