[ErrorHandling] signaturePad Offset 버그 해결

Narcoker·2025년 11월 6일

ErrorHandling

목록 보기
15/16

jquery.signaturepad.min.js
모바일 하이브리드 웹앱에서 사용 중
바닐라 JS

에러 상황 1

모바일 기기 화면 회전 시 펜 오프셋이 부정확해짐

원인

  1. 화면이 회전 시 뷰포트의 넓이/높이가 변경
  2. 뷰포트가 변경됨에 따라 DOM Layout 재계산(Reflow)
  3. <canvas> 컴포넌트는 내부 랜더 버퍼(canvas.width, canvas.height)는 그대로 유지되기 때문

해결 방안

화면 재조정 시 canvas의 width, height를 실제 화면 크기와 비율에 맞게 재설정

canvas.width, canvas.height, canvas.offsetHeight, canvas.offsetWidth
접근이 가능해야함

에러 사항 2 에서 추후 서술


<script>
  	$(window).on("ready", function(){
  		signaturePadInit();
	});

	$(window).on("resize", signaturePadInit);
	
	function signaturePadInit() {
		const canvas = $('#signCanvas')[0];
		const ratio = Math.max(window.devicePixelRatio || 1, 1);
		canvas.width = canvas.offsetWidth * ratio;
		canvas.height = canvas.offsetHeight * ratio;
		canvas.getContext("2d").scale(ratio, ratio);
	
		const signaturePad = $('.sigPad').signaturePad(); 
		signaturePad.clearCanvas();
		signaturePad.updateOptions({
			lineTop : 300,
			penWidth : 8,
			penColour:'#333',
		});
	}
</script>

<body>
  <canvas id="signCanvas" class="pad" width="420" height="140"></canvas>
</body>

에러사항 2

초기 렌더링 시 뷰포트에 canvas가 보이지 않는 경우, 위에서 사용한 초기화 함수 signaturePadInit 제대로 동작안함

원인

에러 사항 1 에서 추후 서술하겠다는 내용

본인이 개발한 화면이 아님

  1. 화면은 위와 같이 구성되어있고 활성화 된 메뉴만 css display 속성을 제어해서 렌더링
  2. 초기 렌더링 시 활성화 된 메뉴는 메뉴-1
  3. 서명 컴포넌트는 메뉴-3에 있음
  4. 렌더링 시 뷰포트에 보이지 않는 컴포넌트의 width/height, offsetWidth/offsetHeight는 Render 차트에서 0이 됨, (인라인 속성으로 지정해도 동일)
  5. 초기화 함수는 window.ready에 있고 메뉴-3이 Render 차트에 없어 서명 컴포넌트의 레이아웃 속성이 0 이 됨

해결 방안

InsersectionObserver를 사용해서 뷰포트에 서명 컴포넌트가 감지됐을 때 초기화 함수 호출


<script>
  	observeSignaturePad(signaturePadInit);
	$(window).on("resize", signaturePadInit);
	
	function signaturePadInit() {
		const canvas = $('#signCanvas')[0];
		const ratio = Math.max(window.devicePixelRatio || 1, 1);
		canvas.width = canvas.offsetWidth * ratio;
		canvas.height = canvas.offsetHeight * ratio;
		canvas.getContext("2d").scale(ratio, ratio);
	
		const signaturePad = $('.sigPad').signaturePad(); 
		signaturePad.clearCanvas();
		signaturePad.updateOptions({
			lineTop : 300,
			penWidth : 8,
			penColour:'#333',
		});
	}

   function observeSignaturePad(callback) {
	  const observer = new IntersectionObserver(entries => {
	  	  const entry = entries[0];
		  if (!entry) return;

		  if(entry.isIntersecting) {
			  callback();
			  observer.unobserve(entry.target);
		  }
	  });
	  observer.observe($('.sigPad')[0]);
};
</script>

<body>
  <canvas id="signCanvas" class="pad" width="420" height="140"></canvas>
</body>

선택 개선 사항

$(window).on("resize", signaturePadInit); 로 인해서
resize 이벤트가 발생할 때마다 초기화 함수 호출됨

Debounce나 Trottling 함수를 래핑하면
불필요한 함수 호출을 줄일 수 있으므로 성능 개선 가능

참고

에러사항 1 - https://github.com/szimek/signature_pad/issues/170

profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글