body의 스크롤을 막을 방법
넷퍼넬3의 '보고서 > 넷퍼넬 ' 페이지에서 상단 오버뷰 클릭했을 때 해당 차트로 이동하는 기능을 구현하던 중 외부 페이지가 아래로 스크롤되는 문제가 발생했다. 보고서 내부가 스크롤 되기 전 외부 먼저 스크롤되어 발생하는 문제로 파악하고, 외부 스크롤을 막아 페이지가 변하는 것을 막아야 한다.
body의 height, overflow 설정하기
첫 번째 방법은 아래와 같이 css에서 body의 height를 100%, overflow를 hidden으로 설정하는 방법이다.
body {
height: 100%;
overflow: hidden;
}
설정하려고 봤더니 이미 이렇게 되어 있었다. overflow를 scroll로 해두고 보았더니, 하단에 scroll 될 공간이 조금 남아있는 것을 확인할 수 있었고, 이를 어떻게 막을 수 있을지 고민해봐야 한다.
위의 방법은 현재 페이지가 body일 경우 스크롤은 막아주지만, 팝업을 띄우고 scrollIntoView를 사용해 아래로 스크롤을 내릴 경우 body의 스크롤을 막아주지는 못한다.
scroll 이벤트 막기
두 번째 방법은 JQuery를 사용해 스크롤 이벤트를 막는 방법이다.
$('body').on('scroll touchmove mousewheel', e=> {
e.preventDefault();
e.stopPropagation();
});
위의 방법은 제대로 동작하지 않았다. preventDefault가 동작하지 않는 이유는 이미 scroll 이벤트가 발생한 후에 preventDefault가 호출되기 때문이다. 더 근본적으로 스크롤을 막을 수 있는 방법에 대해 생각해봐야 한다.
원인 찾음
우측에 숨김된 알림 기록 창이 1289px으로 고정되어 있어서, 이 값이 100%를 넘어가서 스크롤이 발생한다. 알림 기록 창의 크기를 100%보다 작게 줄이면 문제가 해결되지만, px 값을 명시한 이유가 스크롤을 사용하기 위함일 것 같아서 함부로 설정할 수가 없다.
scrollTop(0) => 크롬에서 smooth하게 동작하지 않음
body가 scroll 될 때, scrollTop(0)을 줘 body는 이동하지 못하도록 설정
$('body').on('scroll touchmove mousewheel', e => {
$('body').scrollTop(0);
});
문제가 해결됨. body가 스크롤될 때 탑을 0으로 주기 때문에 body 페이지가 아래로 이동하지 않음.
문제는 해결되나, 기존에 behavior: smooth
는 사용할 수 없어짐. smooth의 경우 body 스크롤 -> 보고서 스크롤의 순서를 거치기 때문에 body가 스크롤되지 않으면 보고서도 스크롤되지 않으나, auto의 경우 body의 스크롤 성공 여부와 상관없이 보고서 내부가 스크롤 되기 때문에 body의 스크롤을 막아도 스크롤이 성공함. => 파이어폭스에서는 behavior: smooth
를 주어도 정상적으로 작동함. 크롬과 파이어폭스에서 동작 방식이 다른 것으로 추정됨.
검색 결과 behavior: smooth
가 에러를 발생하는 경우가 있다고 함. scrollIntoView를 대체할 수 있는 방법을 찾아 적용해야 크롬과 파이어폭스에서 자연스럽게 스크롤되는 화면을 구현할 수 있음.
크롬에서 scrollIntoView
은 전부터 버그가 발생한 경력이 있다.
문제 해결
scrollTo를 사용해서 문제를 해결했다. scrollTo의 적용 엘리먼트는 당연히 body가 아닌 보고서 영역인 resultContent이다.
일단 report.js에 스크롤 하는 메서드를 작성했다.
$scope.moveChart = function(chartId) {
const targetId = $(`#${chartId}`)[0];
$('.resultContent')[0].scrollTo({
top: targetId.offsetTop + 40,
left: 0,
behavior: 'smooth'
});
}
매개변수로 받는 chartId
는 이동하려는 차트의 제목 부분이다. 이를 가지고 제목 부분의 타겟을 targetId
에 저장하고, resultContent
에서 scrollTo를 호출하는데 top에서 40을 더하는 이유는 target의 offsetTop을 측정할 때 body로부터 위치를 측정하기 때문에 해더 크기인 40을 더해주어야 실제 위치가 된다.
이제 transaction_summary.html과 transaction_tps_summary.html 파일에서 테이블을 클릭했을 때 ng-click
이벤트로 moveChart를 실행해주면 된다.