Develop/canvas

LineStyle - lineWidth 라인스타일

GuriZzang 2015. 6. 30. 08:18

guriZzang.com에서 더 많은 html5, canvas의 튜토리얼을 보실 수 있습니다.

guriZzang.com 스터디블로그 바로가기


lineWidth

선의 스타일을 바꾸는 방법은 아래와 같습니다.

  • lineWidth = value
  • 설명 : 선의 두께를 설정합니다.
  • lineCap = type
  • 설명 : 선의 끝 모양을 설정합니다.
  • lineJoin = type
  • 설명 : 두 선이 만나는 지점의 모양을 설정합니다.
  • miterLimit = value
  • 설명 : 두 선이 예각으로 만날 때 접합점의 두께를 제어할 수 있도록, 연결부위의 크기를 제한하는 값을 설정합니다.
  • getLineDash()
  • 설명 : 점선의 설정된 값을 가지고 옵니다.
  • setLineDash(segments)
  • 설명 : 선의 모양을 점선으로 설정합니다.
  • lineDashOffset = value
  • 설명 : 점선의 위치값(?)을 이동시켜 줍니다. 쉽게말해 점선이 움직이는 듯한 효과를 줄 수 있습니다.


그중 선의 두께를 설정하는 lineWidth 입니다. 현재 선의 두께를 설정하며 설정값은 반드시 양수여야 합니다. 초기 설정값은 1.0 단위(px)입니다.


선의 두께는 주어진 경로를 중심으로 한 양끝의 사이를 뜻합니다. 이 말의 뜻은, 경로의 좌우로, 설정된 두께 반만큼의 폭 영역이 그려진다는 것입니다. 캔버스의 좌표는 픽셀을 기준으로 한 것이 아니므로, 수평선이나 수직선을 그릴 때 격자에 딱 맞게 그리려면 각별한 주의를 기울여야 합니다.


아래에 나오는 예제에서는, 선의 두께가 점점 증가하는 10개의 직선을 그렸습니다. 맨 왼쪽에 있는 선의 두께는 1.0 단위이고 오른쪽으로 갈수록 선이 두꺼워지는데, 경로의 위치 때문에 홀수번째 선은 경계선이 흐릿합니다.


격자에 딱 맞는, 흐릿하지 않은 선을 얻으려면 경로에 윤곽선이 어떻게 그려지는지 이해해야 합니다. 아래의 이미지를 보면, 격자는 캔버스의 좌표 격자를 나타냅니다. 격자선 사이에 있는 사각형은 실제 픽셀과 딱 맞아 떨어집니다. 아래에 있는 첫번째 이미지를 보면, (2,1)에서 (5,5)로 사각형이 채워져 있습니다. 사각형의 전체 영역(연한 붉은 색)은 픽셀 경계선 사이에 딱 맞아 떨어집니다.


만일 (3,1)에서 (3,5)로 그리는 직선의 두께가 1.0이라면, 두번째 이미지와 같은 상황이 됩니다. 실제로 그려지는 영역(짙은 파란 색)은 경로의 양옆을 채우는데, 이것은 1 픽셀을 채우는 것이 아니므로 근사값으로 화면에 그려지게 됩니다. 그래서 양옆의 영역(연한 파란색과 짙은 파란 색)으로, 실제 설정한 색과는 다른 흐릿한 색으로 채워지는 것입니다. 이전 예제에서 보듯이 선 두께가 1.0인 선에서 일어난 일입니다.


이렇게 되는 것을 막으려면, 경로를 아주 정밀하게 생성해야 합니다. 선의 두께가 1.0이면 경로의 양쪽으로 0.5 단위만큼이라는 것을 알고 있으니, (3.5,1)에서 (3.5,5)로 그리는 경로를 생성하는 세번째 이미지의 결과는 완벽히 정밀하게 1 픽셀 두께의 수직선이 됩니다.


짝수 두께의 선들은 반으로 나누어도 각각의 반은 정수의 양만큼이기 때문에 픽셀을 조정할 필요가 없습니다.


비트맵이 아닌 벡터 2D 그래픽으로 작업할 때, 작업을 시작할 때는 약간 힘들겠지만, 격자와 경로의 위치에 주의를 기울인다면, 크기를 키우거나 줄이거나 또는 어떠한 변형을 하더라도 그리려는 이미지는 똑바로 보일 것입니다. 1.0 두께의 수직선은 2배로 크기를 키웠을 때, 정확히 2 픽셀 두께의 선이 되며, 올바른 위치에 나타날 것입니다.


참고 : 위에 나온 수직선 그리기 예제를 살펴보면, Y 위치는 정수로 된 격자선 위치를 참조하고 있습니다. 그렇지 않았다면, 끝점에서 픽셀의 반을 차지한 상태로 보였을 것입니다. (초기값이 butt인 lineCap 스타일의 설정값에 따라 다르게 보입니다. 홀수 두께 선들의 좌표를 0.5 픽셀씩 조정하여 다시 계산하고 싶을지도 모릅니다. lineCap 스타일을 square로 설정함으로써, 끝점에서 선의 외곽 경계선은 픽셀에 딱 맞게 자동적으로 확장될 것입니다.)


경로의 시작 지점과 종료 지점의 끝점만이 영향을 받는다는 것에 주목하세요. 만약 closePath()로 경로가 닫힌다면, 시작 지점과 종료 지점은 없는 것입니다. 그 대신, 경로 안에 있는 모든 끝점들은, 초기 설정값이 miter인 lineJoin 스타일의 설정값을 사용하여 이전 부분 및 다음 부분과 이어지는데, 교차되는 점들로 이어진 부분들의 외곽 경계선을 자동적으로 확장하는 효과가 생깁니다. 그렇기 때문에 만약 이들 이어진 부분들이 수직 또는 수평이라면, 그려지는 선들은 각 끝점의 중심에 놓인 픽셀을 가득 채우게 될 것입니다. 이들 선 스타일에 대한 예제는 아래에 나옵니다.





말풍선 그리기

1
2
3
4
5
6
7
8
9
10
function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  for (var i = 0; i < 10; i++){
    ctx.lineWidth = 1+i;
    ctx.beginPath();
    ctx.moveTo(5+i*14,5);
    ctx.lineTo(5+i*14,140);
    ctx.stroke();
  }
}


DEMO