멀티터치 웹 개발

보리스 스무스
Boris Smus

소개

스마트폰과 태블릿 같은 휴대기기에는 일반적으로 사용자 손가락의 상호작용을 캡처하기 위한 정전식 터치 인식 화면이 있습니다. 모바일 웹이 점점 더 정교한 애플리케이션을 가능하게 하도록 발전함에 따라 웹 개발자에게는 이러한 이벤트를 처리할 방법이 필요합니다. 예를 들어 거의 모든 빠른 속도의 게임에서는 플레이어가 한 번에 여러 버튼을 눌러야 하는데, 터치스크린의 맥락에서는 멀티 터치를 의미합니다.

Apple은 iOS 2.0에 터치 이벤트 API를 도입했습니다. Android는 사실상의 표준을 따라잡아 격차를 줄였습니다. 최근 W3C 실무 그룹이 모여 이 터치 이벤트 사양 작업을 진행했습니다.

이 도움말에서는 iOS 및 Android 기기에서 제공하는 터치 이벤트 API와 터치를 지원하는 하드웨어의 데스크톱 Chrome에 대해 자세히 알아보고 빌드할 수 있는 애플리케이션 종류를 살펴보고 몇 가지 권장사항을 제시하며 터치 지원 애플리케이션을 더 쉽게 개발할 수 있는 유용한 기술을 다룹니다.

터치 이벤트

세 가지 기본 터치 이벤트가 사양에 설명되어 있으며 휴대기기에 광범위하게 구현됩니다.

  • touchstart: DOM 요소에 손가락을 놓습니다.
  • touchmove: DOM 요소를 따라 손가락이 드래그됩니다.
  • touchend: DOM 요소에서 손가락이 삭제됩니다.

각 터치 이벤트에는 세 개의 터치 목록이 포함됩니다.

  • touches: 현재 화면에 표시된 모든 손가락 목록입니다.
  • targetTouches: 현재 DOM 요소의 손가락 목록입니다.
  • changedTouches: 현재 이벤트와 관련된 손가락 목록입니다. 예를 들어 touchend 이벤트에서는 삭제된 손가락이 됩니다.

이러한 목록은 터치 정보를 포함하는 객체로 구성됩니다.

  • 식별자: 터치 세션에서 현재 손가락을 고유하게 식별하는 숫자입니다.
  • target: 작업의 대상이었던 DOM 요소입니다.
  • 클라이언트/페이지/화면 좌표: 화면에서 작업이 발생한 위치
  • 반경 좌표 및 rotationAngle: 손가락 모양에 가까운 타원을 설명합니다.

터치 지원 앱

touchstart, touchmovetouchend 이벤트는 손가락 모으기/확대/축소, 회전 등의 일반적인 멀티터치 동작을 비롯하여 거의 모든 종류의 터치 기반 상호작용을 지원하기에 충분한 기능 집합을 제공합니다.

이 스니펫에서는 한 손가락 터치를 사용하여 DOM 요소를 드래그할 수 있습니다.

var obj = document.getElementById('id');
obj.addEventListener('touchmove', function(event) {
  // If there's exactly one finger inside this element
  if (event.targetTouches.length == 1) {
    var touch = event.targetTouches[0];
    // Place element where the finger is
    obj.style.left = touch.pageX + 'px';
    obj.style.top = touch.pageY + 'px';
  }
}, false);

다음은 화면에 모든 현재 터치를 표시하는 샘플입니다. 기기의 반응성을 감지하는 것만으로도 유용합니다.

손가락 추적
// Setup canvas and expose context via ctx variable
canvas.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.touches.length; i++) {
    var touch = event.touches[i];
    ctx.beginPath();
    ctx.arc(touch.pageX, touch.pageY, 20, 0, 2*Math.PI, true);
    ctx.fill();
    ctx.stroke();
  }
}, false);

데모

Paul Irish 및 기타 제작자의 캔버스 기반 그리기 데모와 같이 여러 가지 흥미로운 멀티터치 데모가 이미 출시되어 있습니다.

스크린샷 그리기

다음은 CSS3 변환 및 전환과 캔버스를 사용하는 Fruit Ninja 클론인 기술 데모 브라우저 닌자입니다.

브라우저 닌자

권장사항

확대/축소 방지

스와이프 및 동작은 스크롤 및 확대/축소와 같은 브라우저 동작과 연결되는 경우가 많기 때문에 기본 설정은 멀티터치에 적합하지 않습니다.

확대/축소를 사용 중지하려면 다음 메타 태그를 사용하여 사용자가 확장할 수 없도록 표시 영역을 설정합니다.

<meta name="viewport" 
  content="width=device-width, initial-scale=1.0, user-scalable=no>

표시 영역 설정에 관한 자세한 내용은 이 모바일 HTML5 도움말을 확인하세요.

스크롤 방지

일부 휴대기기에는 스크롤이 콘텐츠 경계를 초과하면 뷰가 다시 튀어나오는 기본 iOS 오버스크롤 효과와 같은 touchmove의 기본 동작이 있습니다. 이는 다수의 멀티터치 애플리케이션에서 혼란스러워하며 쉽게 사용 중지할 수 있습니다.

document.body.addEventListener('touchmove', function(event) {
  event.preventDefault();
}, false); 

신중하게 렌더링

복잡한 여러 손가락 동작이 포함된 멀티터치 애플리케이션을 작성하는 경우 한 번에 너무 많은 동작을 처리하게 되므로 터치 이벤트에 반응하는 방식에 주의해야 합니다. 화면에 모든 터치를 그리는 이전 섹션의 샘플을 생각해 보세요. 터치 입력이 있는 즉시 그릴 수 있습니다.

canvas.addEventListener('touchmove', function(event) {
  renderTouches(event.touches);
}, false);

그러나 이 기법은 화면에서 손가락의 수에 따라 확장되지 않습니다. 대신 모든 손가락을 추적하고 루프로 렌더링하여 성능을 크게 높일 수 있습니다.

var touches = []
canvas.addEventListener('touchmove', function(event) {
  touches = event.touches;
}, false);

// Setup a 60fps timer
timer = setInterval(function() {
  renderTouches(touches);
}, 15);

targetTouches 및 changedTouches 사용

event.touches는 DOM 요소의 타겟에 있는 손가락뿐만 아니라 화면에 접촉하는 모든 손가락의 배열이라는 점을 기억하세요. 대신 event.targetTouches 또는 event.changedTouches를 사용하는 것이 훨씬 더 유용할 수 있습니다.

마지막으로, 모바일용으로 개발하고 있으므로 Eric Bidelman의 도움말과 이 W3C 문서에서 설명하는 일반적인 모바일 권장사항을 알고 있어야 합니다.

기기 지원

안타깝게도 터치 이벤트 구현은 완전성과 품질이 크게 다릅니다. 지원되는 이벤트 및 touchmove 실행 해상도 등 터치 API 구현에 관한 몇 가지 기본 정보를 표시하는 진단 스크립트를 작성했습니다. Nexus One과 Nexus S 하드웨어에서 Android 2.3.3, Xoom에서 Android 3.0.1, iPad 및 iPhone에서 iOS 4.2를 테스트했습니다.

간단히 말해, 테스트된 모든 브라우저는 touchstart, touchendtouchmove 이벤트를 지원합니다.

사양에서 세 가지 터치 이벤트를 추가로 제공하지만 테스트된 브라우저에서는 이를 지원하지 않습니다.

  • touchenter: 움직이는 손가락이 DOM 요소에 들어갑니다.
  • touchleave: 움직이는 손가락이 DOM 요소를 떠납니다.
  • touchcancel: 터치가 중단됩니다 (구현별로 다름).

각 터치 목록 내에서 테스트된 브라우저는 touches, targetTouches, changedTouches 터치 목록도 제공합니다. 그러나 테스트된 브라우저에서는 화면을 터치하는 손가락의 모양을 지정하는 radiusX, radiusY, rotationAngle을 지원하지 않습니다.

터치 동작 중에는 테스트된 모든 기기에서 초당 약 60회에 이벤트가 실행됩니다.

Android 2.3.3 (Nexus)

Android Gingerbread 브라우저 (Nexus One 및 Nexus S에서 테스트됨)에서는 멀티터치 지원이 없습니다. 이는 알려진 문제입니다.

Android 3.0.1 (Xoom)

Xoom 브라우저에는 기본적인 멀티터치 지원이 있지만 단일 DOM 요소에서만 작동합니다. 브라우저가 서로 다른 DOM 요소의 두 가지 동시 터치에 올바르게 응답하지 않습니다. 즉, 다음은 동시에 두 개의 터치에 반응합니다.

obj1.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.targetTouches; i++) {
    var touch = event.targetTouches[i];
    console.log('touched ' + touch.identifier);
  }
}, false);

하지만 다음은 그렇지 않습니다.

var objs = [obj1, obj2];
for (var i = 0; i < objs.length; i++) {
  var obj = objs[i];
  obj.addEventListener('touchmove', function(event) {
    if (event.targetTouches.length == 1) {
      console.log('touched ' + event.targetTouches[0].identifier);
    }
  }, false);
}

iOS 4.x (iPad, iPhone)

iOS 기기는 멀티 터치를 완벽하게 지원하고 꽤 많은 손가락을 추적할 수 있으며 브라우저에서 반응성이 뛰어난 터치 환경을 제공합니다.

개발자 도구

모바일 개발의 경우 데스크톱에서 프로토타입을 제작하기 시작한 다음 지원하려는 기기에서 모바일 관련 부분을 처리하는 것이 더 쉬운 경우가 많습니다. 멀티 터치는 대부분의 PC에 터치 입력이 없으므로 PC에서 테스트하기 어려운 기능 중 하나입니다.

모든 변경사항을 서버로 푸시한 다음 기기에 로드해야 하므로 모바일에서 테스트해야 하므로 개발 주기가 길어질 수 있습니다. 그런 다음 실행하고 나면 애플리케이션을 디버그할 수 있는 작업이 거의 없습니다. 태블릿과 스마트폰에는 웹 개발자 도구가 없기 때문입니다.

이 문제를 해결하려면 개발 머신에서 터치 이벤트를 시뮬레이션해야 합니다. 원터치의 경우 마우스 이벤트를 기반으로 터치 이벤트를 시뮬레이션할 수 있습니다. 멀티터치 이벤트는 최신 Apple MacBook과 같이 터치 입력이 있는 기기가 있는 경우 시뮬레이션할 수 있습니다.

원터치 이벤트

데스크톱에서 원터치 이벤트를 시뮬레이션하려는 경우 Chrome에서 개발자 도구의 터치 이벤트 에뮬레이션을 제공합니다. 개발자 도구를 열고 설정 톱니바퀴를 선택한 다음 '재정의' 또는 '에뮬레이션'을 선택하고 '터치 이벤트 에뮬레이션'을 사용 설정합니다.

다른 브라우저의 경우 페이지에서 터치 이벤트를 시뮬레이션하고 커다란 손으로 부팅할 수 있는 팬텀 림을 사용해 볼 수 있습니다.

여러 플랫폼에서 터치 및 마우스 이벤트를 통합하는 Touchable jQuery 플러그인도 있습니다.

멀티터치 이벤트

멀티터치 웹 애플리케이션이 멀티터치 트랙패드 (예: Apple MacBook 또는 MagicPad)의 브라우저에서 작동하도록 하기 위해 MagicTouch.js 폴리필을 만들었습니다. 트랙패드에서 터치 이벤트를 캡처하여 표준 호환 터치 이벤트로 변환합니다.

  1. npTuioClient NPAPI 플러그인을 다운로드하여 ~/Library/Internet Plug-Ins/에 설치합니다.
  2. Mac의 MagicPad용 TongSeng TUIO 앱을 다운로드하고 서버를 시작합니다.
  3. npTuioClient 콜백을 기반으로 사양과 호환되는 터치 이벤트를 시뮬레이션하는 자바스크립트 라이브러리인 MagicTouch.js를 다운로드합니다.
  4. 다음과 같이 애플리케이션에 magictouch.js 스크립트와 npTuioClient 플러그인을 포함합니다.
<head>
  ...
  <script src="/path/to/magictouch.js"></script>
</head>

<body>
  ...
  <object id="tuio" type="application/x-tuio" style="width: 0px; height: 0px;">
    Touch input plugin failed to load!
  </object>
</body>

플러그인을 사용 설정해야 할 수도 있습니다.

magictouch.js를 사용한 실시간 데모는 paulirish.com/demo/multi에서 확인할 수 있습니다.

이 접근 방식은 Chrome 10에서만 테스트했지만, 다른 최신 브라우저에서는 약간의 조정만으로도 작동할 것입니다.

컴퓨터에 멀티터치 입력이 없으면 reacTIVision과 같은 다른 TUIO 추적기를 사용하여 터치 이벤트를 시뮬레이션할 수 있습니다. 자세한 내용은 TUIO 프로젝트 페이지를 참고하세요.

이 동작은 OS 수준의 멀티터치 동작과 동일할 수도 있습니다. OS X에서는 시스템 환경설정의 트랙패드 환경설정 창으로 이동하여 시스템 전체 이벤트를 구성할 수 있습니다.

멀티 터치 기능이 모바일 브라우저에서 더 광범위하게 지원되면서 새로운 웹 애플리케이션에서 이 풍부한 API를 최대한 활용할 수 있게 되어 매우 기쁩니다.