해상도에 따라 달라지는 캔버스 만들기

너구리오리·2021년 8월 25일
0
post-thumbnail

요즘 웹 페이지는 반응형이 기본이죠.
이번 포스트에서는 JS그림판이 디바이스 해상도에 따라 캔버스 크기가 달라지도록 반응형으로 구현해보고, 캔버스 사이즈가 달라졌을 때 필요한 JavaScript 후처리를 알아보겠습니다.


반응형 웹 만들기

반응형 웹 페이지란?

같은 페이지인데 브라우저 창 크기를 늘이거나 줄이면 레이아웃이 달라지는 홈페이지를 본 적 있으신가요? 이렇게 웹 페이지가 디바이스 종류에 따라 크기가 자동으로 조절되는 웹 페이지를 반응형(responsive) 웹이라고 합니다.

PC/모바일/태블릿 등 디바이스마다 화면 비율이나 해상도가 다르기 때문에 화면 구성이 달라져야 하는데, PC 버전과 모바일 버전을 각각 개발하지 않고 하나만 개발한 후 CSS를 통해 동적으로 레이아웃하도록 하는 원리입니다.

CSS 미디어 쿼리로 반응형 웹 구현하기

CSS 모듈 중 미디어 쿼리를 사용하면 반응형 웹을 비교적 쉽게 만들 수 있습니다.
미디어 쿼리 구문의 기본형은 다음과 같습니다.

@media 미디어 유형 and [조건] and [조건] ... {
    body { /* 스타일을 적용할 태그 */
    	(스타일 내용)	
    }
}

미디어 유형에는 all, print, screen, tv 등을 지정할 수 있고 앞에 옵션 only, not 등을 적용할 수 있습니다. 저는 컴퓨터 스크린과 스마트폰 스크린을 포함하는 screen을 지정하겠습니다.

그리고 스마트폰, 태블릿, PC 등 여러 기기의 다양한 해상도를 고려해 캔버스 사이즈가 달라지도록 해보겠습니다.

기준은 단말기의 가로 너비(device-width) 또는 웹 페이지 가로 너비(width)로 정하고, min/max 범위를 지정하여 가로 너비가 그 범위 안에 들어올 때 스타일이 적용되도록 합니다.

단말기의 방향(orientation)은 세로일 때 portrait, 가로일 때 landscape입니다.

.canvas {
    width: 500px;
    height: 500px;
    background-color: white;
    border-radius: 15px;
    box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0px 0px 3px rgba(0, 0, 0, 0.5);
    position: relative;
}
/* 스마트폰 세로 */
@media screen and (max-device-width: 320px){
    .canvas {
        width: 80vmin;
        height: 80vmin;
    }
}
/* 태블릿 세로 */
@media screen and (min-width : 321px) and (max-width : 767px) and (orientation : portrait ) {
    .canvas {
        width: 90vmin;
        height: 90vmin;
    }
}
/* iPad Pro 세로 */
@media screen and (min-width : 768px) and (orientation : portrait ) {
    .canvas {
        width: 900px;
        height: 900px;
    }
}
/* 스마트폰 가로 */
@media screen and (max-width : 767px) and (orientation : landscape ) {
    .canvas {
        width: 70vmax;
        height: 60vmin;
    }
}
/* 태블릿 가로 */
@media screen and (min-width : 768px) and (max-width : 1365px) and (orientation : landscape ) {
    .canvas {
        width: 90vmax;
        height: 70vmin;
    }
}
/* iPad Pro 가로, 데스크탑 */
@media screen and (min-width : 1366px) and (max-width : 1599px) and (orientation : landscape ) {
    .canvas {
        width: 90vmax;
        height: 80vmin;
    }
}
/* 큰 모니터 16:9 */
@media screen and (min-width : 1600px) {
    .canvas {
        width: 1600px;
        height: 900px;
    }
}

저는 이렇게 여러 해상도 단계와 세로/가로 방향을 구분해서 캔버스 사이즈가 달라지도록 구현했습니다. 실제 코드에서는 .canvas 클래스 외에도 크기 조정이 필요한 다른 요소들도 함께 포함하면 예쁜 반응형 웹을 만드실 수 있습니다.

해상도/기기/플랫폼을 나누는 기준?

반응형 웹 제작을 위해 모바일, 태블릿, PC 등을 구분하고자할 때 기준이 되는 해상도는 얼마일까요? 보통 기준이 되는 해상도를 중단점(Break Point)라고 하는데 중단점의 정답은 없지만 많이 쓰는 표준적인 값은 있습니다. 포털에 검색해보면 다음과 같이 구분하는 경우가 흔하고, 저 또한 이러한 기준을 참고하여 만들었습니다.

세로 방향가로 방향
모바일min-width: 320pxmin-width: 480px
태블릿min-width: 768pxmin-width: 1024px
데스크톱min-width: 1024px

일반적으로 사람들이 많이 쓰는 기기(ex. iPhone, iPad)의 해상도를 고려해서 레이아웃을 설계하시는 것이 좋겠죠?

만약 특정 기기(예를 들어 iPhone X)에 맞추고 싶으시다면 해당 기기의 width 및 height를 인터넷(yesviz.com/devices.php)에서 찾으신 후에 width/height를 동시에 지정하면 됩니다.

@media screen and (min-device-width: 375px) and (min-device-height: 812px) {
	/* iPhone X 는 가로 375 px, 세로 812 px 입니다. */
}

PC에서 반응형 테스트 하기

위에서 반응형 웹 CSS를 작성했으니 실제 서비스를 배포하기 전에 테스트를 해봐야 합니다.
그런데 PC로 작업 중인 결과물을 모바일에서 테스트하려면 어떻게 해야 할까요?

저는 크롬 개발자 도구 안에서 모바일 창 기능을 사용합니다.
브라우저에서 F12를 눌러 개발자 도구에 들어간 후 Toggle Device Toolbar 버튼을 누르면 브라우저 안에서 여러 종류의 모바일 기기를 미리 테스트 해볼 수 있습니다. (아래 스크린샷 참고)

마우스 이벤트도 터치 이벤트로 바뀌므로 참고하세요!

이렇게 크롬에서 디바이스를 바꿔가며 모바일 환경에서 반응형 웹이 잘 작동하는지 확인할 수 있습니다.


캔버스에 동적 사이즈 적용하기

반응형 CSS 적용 후 캔버스가 이상해?

HTML <canvas> 태그에는 두 가지 사이즈가 있습니다. 이에 대해 상세하게 설명한 페이지는 참고자료2에 있습니다. 여기서는 쉬운 설명으로 이해를 돕기 위해 우리끼리의 용어로 정의해보겠습니다.

실제 화면에서 우리 눈에 보이는 캔버스의 width/height는 스타일 사이즈라고 하겠습니다. CSS 미디어 쿼리를 통해 위와 같이 반응형 웹을 만들면, 스타일 사이즈는 기기에 따라 달라지면서 적절한 위치에 그럴듯하게 배치됩니다. 하지만 이 상태에서 캔버스 위에 그림을 그리려고 하면 잘 그려지지 않거나 이상하게 그려집니다. 왜 그럴까요?

캔버스가 실제 그림이 그려지는 영역은 스타일 사이즈가 아닌, 스크립트 코드 상에서 정의된 width/height 값이 됩니다. 이를 픽셀 사이즈라고 부르기로 합시다.

이 픽셀 사이즈는 보통 이런 식으로 script 파일에 선언합니다.

const canvas = document.getElementById("jsCanvas");

canvas.width = 100px;
canvas.height = 100px;

이제 실제 스크립트 상에서 사용할 width와 height가 각각 100px로 정해졌습니다.

그런데 이렇게 정의된 상태에서 미디어 쿼리로 인해 캔버스 스타일 사이즈가 200px X 200px 로 바뀐다면 어떻게 될까요? 정답은 스타일 사이즈가 변경되어도 캔버스 내부 픽셀 사이즈는 변하지 않습니다.

눈에 보이는 영역은 200px X 200px 이므로 캔버스 영역에 총 40,000개의 픽셀이 존재할 것 같지만, 실제로는 캔버스 영역 내부에 처음 선언된 100px X 100px 만큼의 픽셀 해상도가 유지되고 있는 상태가 됩니다.

이 상태가 되면 눈에 보이는 화소보다 캔버스 내부 화소가 2배 크므로, 전체 그림이 2배 확대된 비율로 보이게 됩니다.

그러므로 반응형 웹에 캔버스를 사용한다면, 눈에 보이는 스타일 사이즈가 변할 때 실제 스크립트 픽셀 사이즈가 함께 변하도록 우리가 직접 js 파일에 프로그래밍해야 합니다.

간단한 해결 방법

여러가지 해결 방법이 있겠지만 제가 찾은 간단한 방법을 소개하겠습니다.

어떤 디바이스에서 로딩하냐에 따라 다른 해상도로 캔버스가 만들어진다면, 로딩 직후 캔버스 CSS 사이즈가 정해졌을 때 스크립트 사이즈를 유동적으로 정의하면 됩니다.

const { width, height } = canvas.getBoundingClientRect();
canvas.width = width;
canvas.height = height;

이 코드를 app.js 상단에서 수행하면 canvas가 레이아웃 된 후 script가 처음 실행될 때 캔버스의 CSS 스타일 사이즈와 동일하게 스크립트 픽셀 사이즈를 정의할 수 있습니다.

로딩 직후의 캔버스 동적 할당 문제는 위 코드로 해결되지만, 웹 서비스 도중에 캔버스 사이즈가 달라지는 경우에 대해서는 아직 해결되지 않았습니다. 이에 대해서는 추후 다른 포스트에서 다뤄보도록 하겠습니다.

감사합니다.


참고자료

  1. 고경희, "Do it! HTML+CSS+자바스크립트 웹 표준의 정석", 2021, 이지스퍼블리싱
  2. WebGL Canvas 크기 조정

0개의 댓글