Javascript

Canvas 모바일에서 사용하기(touchevent)

joy_lee 2021. 11. 12. 18:11

페이지를 모바일에서도 사용할 수 있도록 레이아웃도 바꿨는데 터치가 안된다...! 알아봤더니 터치 이벤트는 mouse이벤트랑 다르다고 한다. 캔버스를 모바일 기기에서도 사용할 수 있도록 코드를 추가했다.

 

목표

핸드폰에서도 캔버스 사용하기

 

터치이벤트

터치 이벤트는 세 가지 종류가 있다.

touchstart 화면에서 터치가 일어났을 때 발생하는 이벤트
touchmove 터치한 곳이 이동할 때 발생하는 이벤트
touchend 사용자가 화면에서 터치를 떼서 터치한 곳이 사라질 때 발생하는 이벤트

이 이벤트들을 mouse이벤트와 같이 addEventListener로 연결해야 한다.

1
2
3
canvas.addEventListener("touchmove", touchMove, false);
canvas.addEventListener("touchstart", touchStart, false);
canvas.addEventListener("touchend", touchEnd, false);
cs

각각의 이벤트가 발생했을 때 실행할 함수를 만들어주었다.

 

 

그리고 터치한 좌표를 구하는 함수를 따로 만들었다.

1
2
3
4
5
6
function getTouchPos(e) {
    return {
        x: e.touches[0].clientX - e.target.offsetLeft,
        y: e.touches[0].clientY - e.target.offsetTop + document.documentElement.scrollTop
    }
}
cs

데스크탑 페이지의 경우, x: e.offsetX, y: e.offsetY로 쉽게 마우스의 좌표를 알 수 있었다. 하지만 모바일 페이지에서는 다른 방법으로 구해야했다.

 

canvas 내의 좌표를 구하기 위해서는 e.touches[0].clientY 에서 e.target.offsetTop을 빼줘야 한다.

x좌표는 두 값을 빼면 바로 구할 수 있다.

y좌표는 만약 스크롤해서 페이지가 이동한 상황이라면, document.documentElement.scrollTop을 더해줘야 한다.

 

touchStart는 아래와 같이 작성해준다.

1
2
3
4
5
6
7
function touchStart(e) {
    e.preventDefault();
    drawing = true;
    const { x, y } = getTouchPos(e);
    startX = x;
    startY = y;
}
cs

 

touchMove는 아래와 같다.

1
2
3
4
5
6
7
function touchMove(e) {
    if(!drawing) return;
    const { x, y } = getTouchPos(e);
    draw(x, y);
    startX = x;
    startY = y;
}
cs

좌표정보를 getTouchPos(e)를 통해 가져오는 것 빼고 데스크탑 페이지의 mouseDown(), mouseMove()와 같다.

 

터치를 끝냈을 때 실행되는 touchEnd는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
function touchEnd(e) {
    if(!drawing) return;
    // 점을 찍을 경우 위해 마지막에 점을 찍는다.
    // touchEnd 이벤트의 경우 위치정보가 없어서 startX, startY를 가져와서 점을 찍는다.
    ctx.beginPath();
    ctx.arc(startX, startY, ctx.lineWidth/202*Math.PI);
    ctx.fillStyle = ctx.strokeStyle;
    ctx.fill();
    drawing = false;
}
 
cs

 

mouseUp과 다른 점은, mouseUp의 경우 어디에서 마우스 클릭을 뗐는지 위치정보가 있지만, touchEnd 이벤트는 어디에서 터치를 끝냈는지 정보가 없었다. 그래서 터치를 끝냈다는 정보만 받고, 그리던 선의 마지막 위치에서 점을 찍는 것으로 선을 마무리한다.(데스크탑 사이트에도 점을 찍는 코드를 추가했다.)

점은 ctx.arc()로 그 자리에(startX, startY) 원을 그려주었다.

 

 

참고한 사이트

https://developer.mozilla.org/ko/docs/Web/API/Touch_events

 

Touch events - Web API | MDN

터치를 기반으로 한 양질의 서비스를 제공하기 위해, Touch Events(터치이벤트)는 터치로 인한 움직임을 감지할 능력을 제공합니다.

developer.mozilla.org