04. 모바일 관련 문제들 해결하기 (우클릭 방지, input range 등)
body {
...
-webkit-touch-callout: none;
}
모바일에서 안되는 것 투성이...?
이 전 포스트에서 CI / CD 툴을 연동한 이유는 사실 이번 포스팅의 문제를 해결하기 위해 구축한 사전 작업이다.
분명 PC 브라우저에서 화면의 레이아웃이나 동작들이 모두 이상없이 잘 작동했는데, 모바일로 들어가보니 되는 기능이 하나 없었다.
그 중 대표적인 몇 가지를 적어 보자면 아래와 같다.
1. 화면 레이아웃 깨짐 (100vh 문제 포함)
2. 이미지 버튼을 꾹 누르면 브라우저의 이미지 저장 창이 나타나서 음악을 5초뒤, 5초 전으로 건너 뛸 수 없음
3. <input type='range'> 에서 드래그 작동 안함
4. javascript로 volume 컨트롤이 안됨
5. drag & drop 기능 작동 안함
설렌다... 고칠게 참 많다...
1. 화면 레이아웃 깨짐 현상 수정
우선 스크롤이 생긴 이유는 앱의 높이를 100vh로 설정했는데, 모바일의 브라우저에서는 이 100vh가 상단 주소입력창과 하단 네비게이션 영역을 포함하기 때문에 실제 뷰포트보다 커져 스크롤이 생긴다.
이 문제를 해결하기위해 javascript로 브라우저 내부 화면의 크기를 직접 변수로 설정해주고, 스크롤이 발생하지 않도록 만들었다.
(자세한 내용은 https://blog.leehov.in/39 참조)
그리고 리펙토링을 통해 일부 필요없는 div를 없앴다.
모바일에서는 일부 div에서 100%가 적용이 되지 않는 경우가 있기 때문에, vh나 em등의 수치를 사용하면 해결된다.
2. 이미지 버튼 우클릭 현상
일단 이미지 버튼을 꾹 누르면 우클릭이 작동해 모바일 브라우저의 창이 뜨는데(위 사진 참조) 이를 막기 위해서는 두 가지를 해 줘야한다.
우선 안드로이드에서 우클릭을 막기 위해서는 body태그에 oncontextmenu라는 이벤트가 발생되었을 때 아래와 같이 함수를 호출하면 된다.
onContextMenu={
(e) => {
e.preventDefault();
return false;
}
}
그리고 두 번째로 iOS에서는 CSS파일의 body 부분에 해당 줄을 추가하면 된다.
-webkit-touch-callout: none;
3. input type = 'range' 태그 드래그 문제
mobile에서는 handle이 아닌 bar 중간을 클릭해서 움직이면 value가 처음 터치를 할 때 빼고는 변하지 않는다.
때문에 onTouchStart, onTouchMove 이벤트를 연결해서 직접 value를 변경해주었다.
4. volume 컨트롤...
iOS에서는 volume 컨트롤을 기기로만 설정 할 수 있도록 되어 있어서 인 앱 안에서 volume컨트롤이 불가능하다.
때문에, 기기를 체크해서 ios라면 audio 버튼이 볼륨 컨트롤러가 아닌 음소거 on/off 버튼이 되도록 변경해야 했는데,
JavaScript로 현재 브라우저가 어떤 환경에서 실행 되었는지 확인할 수 있는 코드가 있다!
window.navigator.userAgent
Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1
여기서 iPad 혹은 iPhone이라는 단어가 들어간 지 find 메소드로 확인 후 만약 해당 단어가 포함된다면 volume을 온 오프로 설정하는 코드를 추가해주었다 🙂
* audio 앨리먼트의 muted를 true / false 로 설정해주면 음소거의 상태가 변한다.
(volume = 0 이나 mute = true 등은 작동하지 않는다.)
5. Drag & Drop 이벤트 작동 안함
아직 음악 리스트는 모바일에서 drag기능으로 순서 변경이 안되는데, 이 문제는 3번과 같이 touch관련 이벤트를 사용해서 변경을 했다.
구조가 좀 까다로운데, 다음에도 사용할 수 있도록 라이브러리 형식으로 만들어보면 어떨까 싶다! 🙂