선 스타일
일련의 속성을 통해 선 스타일을 설정할 수 있습니다.
lineWidth = value lineCap = type lineJoin = type miterLimit = value
이러한 속성에 대해 자세히 설명하겠지만 다음 예를 보면 더 쉽게 이해할 수 있습니다.
lineWidth 속성 예시
이 속성은 현재 그려지는 선의 두께를 설정합니다. 속성 값은 양수여야 합니다. 기본값은 1.0입니다. 선 너비는 중앙에서 측면까지 주어진 경로의 두께를 나타냅니다. 즉, 경로 양쪽에 선 너비의 절반을 그립니다. 캔버스 좌표는 픽셀과 직접적으로 일치하지 않으므로 정확한 가로 또는 세로 선을 얻을 때는 특별한 주의를 기울여야 합니다. 아래 예에서는 너비가 증가하면서 10개의 선이 그려집니다. 가장 왼쪽 선의 너비는 1.0 단위입니다. 또한 경로의 위치 문제로 인해 가장 왼쪽과 홀수 너비의 모든 선을 정확하게 렌더링할 수 없습니다.
rree정확한 선을 얻으려면 선이 어떻게 그려지는지 이해해야 합니다. 아래 그림과 같이 그리드는 캔버스의 좌표 그리드를 나타내는 데 사용됩니다. 각 그리드는 화면의 픽셀에 해당합니다. 첫 번째 그림에서는 직사각형 (2,1) ~ (5,5)가 채워지고 전체 영역의 경계가 정확히 픽셀의 가장자리에 있으므로 결과 직사각형의 가장자리가 선명해집니다.
(3,1)에서 (3,5)까지 너비를 1.0으로 선을 그리면 두 번째 그림과 같은 결과가 나옵니다. 실제 채우기 영역(진한 파란색)은 경로 양쪽에 있는 픽셀의 절반까지만 확장됩니다. 이러한 절반 픽셀은 대략적인 방식으로 렌더링됩니다. 즉, 해당 픽셀은 부분적으로만 색상이 지정되어 전체 영역(밝은 파란색과 진한 파란색)이 실제 획 색상 톤의 절반으로 채워집니다. 이것이 위의 예에서 너비가 1.0인 선이 정확하지 않은 이유입니다. 이 문제를 해결하려면 경로를 보다 정밀하게 제어해야 합니다. 두께가 1.0인 선은 경로 양쪽에서 픽셀의 절반만큼 확장된 다음 세 번째 그림처럼 (3.5,1)에서 (3.5,5)까지 선을 그리면 그 가장자리가 정확하게 떨어지는 것으로 알려져 있습니다. 픽셀 경계에서 채워지며 너비가 1.0인 라인이 정확하게 채워집니다. 너비가 균일한 선의 경우 각 측면의 픽셀 수는 정수입니다. 그러면 경로가 픽셀 포인트 내부가 아닌 픽셀 사이(예: (3,1)에서 (3,5)까지)에 떨어지기를 원합니다. 중간에. 또한 해당 예의 수직선에는 Y 좌표가 정확히 그리드 선에 위치합니다. 그렇지 않은 경우 끝점에도 절반 렌더링된 픽셀이 있습니다. 확장 가능한 2D 그래픽으로 작업하는 것은 처음에는 약간 어려울 수 있지만 픽셀 격자와 경로 위치 사이의 관계에 미리 주의를 기울이면 크기가 조정되거나 변형된 후에도 그래픽이 계속 좋아 보일 수 있습니다. 선 너비 2배 확대 후 , 너비가 1.0인 수직선은 너비가 2.0인 선명한 선이 되어 나타나야 할 위치에 나타납니다.
lineCap
속성 예시
속성
lineCap의 포인터는 선분의 끝점이 표시되는 방식을 결정합니다. 엉덩이형, 원형, 정사각형의 세 가지 유형 중 하나일 수 있습니다. 기본값은 엉덩이입니다.
이 예에서는 세 개의 직선을 그리고 각각에 서로 다른 lineCap 값을 할당했습니다. 또한 두 개의 보조선이 있는데, 이들 사이의 차이를 더 명확하게 보기 위해 세 개의 선의 시작점과 끝점이 모두 보조선에 있습니다. 가장 왼쪽 줄은 기본 버튼을 사용합니다. 안내선과 같은 높이인지 확인하세요. 가운데는 선 너비의 절반 반경이 끝점에 추가된 반원이 있는 둥근 효과입니다. 오른쪽은 정사각형의 효과입니다. 끝점은 동일한 폭과 선 폭의 절반 높이의 정사각형으로 추가됩니다.
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(); } }
lineJoin
속성 예시
lineJoin的属性值决定了图形中两线段连接处所显示的样子。它可以是这三种之一:round,bevel和miter。默认是miter。
这里我同样用三条折线来做例子,分别设置不同的lineJoin值。最上面一条是round的效果,边角处被磨圆了,圆的半径等于线宽。中间和最下面一条分别是 bevel 和 miter的效果。当值是miter的时候,线段会在连接处外侧延伸直至交于一点,延伸效果受到下面将要介绍的miterLimit属性的制约。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); var lineJoin = ['round','bevel','miter']; ctx.lineWidth = 10; for (var i=0;i<lineJoin.length;i++){ ctx.lineJoin = lineJoin[i]; ctx.beginPath(); ctx.moveTo(-5,5+i*40); ctx.lineTo(35,45+i*40); ctx.lineTo(75,5+i*40); ctx.lineTo(115,45+i*40); ctx.lineTo(155,5+i*40); ctx.stroke(); } }
miterLimit
属性的演示例子
就如上一个例子所见的应用miter
的效果,线段的外侧边缘会延伸交汇于一点上。线段直接夹角比较大的,交点不会太远,但当夹角减少时,交点距离会呈指数级增大。miterLimit
属性就是用来设定外延交点与连接点的最大距离,如果交点距离大于此值,连接效果会变成了 bevel。
渐变 Gradients
就好像一般的绘图软件一样,我们可以用线性或者径向的渐变来填充或描边。我们用下面的方法新建一个canvasGradient
对象,并且赋给图形的fillStyle或strokeStyle
属性。
createLinearGradient(x1,y1,x2,y2) createRadialGradient(x1,y1,r1,x2,y2,r2)
createLinearGradient方法接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)。createRadialGradient方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。
var lineargradient = ctx.createLinearGradient(0,0,150,150); var radialgradient = ctx.createRadialGradient(75,75,0,75,75,100);
创建出canvasGradient对象后,我们就可以用addColorStop方法给它上色了。
addColorStop(position, color)
addColorStop
方法接受 2 个参数,position参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。color参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)。你可以根据需要添加任意多个色标(color stops)。下面是最简单的线性黑白渐变的例子。
var lineargradient = ctx.createLinearGradient(0,0,150,150); lineargradient.addColorStop(0,'white'); lineargradient.addColorStop(1,'black');
createLinearGradient
的例子
本例中,我弄了两种不同的渐变。第一种是背景色渐变,你会发现,我给同一位置设置了两种颜色,你也可以用这来实现突变的效果,就像这里从白色到绿色的突 变。一般情况下,色标的定义是无所谓顺序的,但是色标位置重复时,顺序就变得非常重要了。所以,保持色标定义顺序和它理想的顺序一致,结果应该没什么大问题。
第二种渐变,我并不是从 0.0 位置开始定义色标,因为那并不是那么严格的。在 0.5 处设一黑色色标,渐变会默认认为从起点到色标之间都是黑色。你会发现,strokeStyle
和fillStyle属性都可以接受canvasGradient对象。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); // Create gradients var lingrad = ctx.createLinearGradient(0,0,0,150); lingrad.addColorStop(0, '#00ABEB'); lingrad.addColorStop(0.5, '#fff'); //lingrad.addColorStop(0.5, '#26C000'); //lingrad.addColorStop(1, '#fff'); var lingrad2 = ctx.createLinearGradient(0,50,0,95); lingrad2.addColorStop(0.5, '#000'); lingrad2.addColorStop(1, 'rgba(0,0,0,0)'); // assign gradients to fill and stroke styles ctx.fillStyle = lingrad; ctx.strokeStyle = lingrad2; // draw shapes ctx.fillRect(10,10,130,130); ctx.strokeRect(50,50,50,50);
createRadialGradient
的例子
这个例子,我定义了 4 个不同的径向渐变。由于可以控制渐变的起始与结束点,所以我们可以实现一些比(如在 Photoshop 中所见的)经典的径向渐变更为复杂的效果。(经典的径向渐变是只有一个中心点,简单地由中心点向外围的圆形扩张)。这里,我让起点稍微偏离终点,这样可以达到一种球状 3D 效果。但最好不要让里圆与外圆部分交叠,那样会产生什么效果就真是不得而知了。4 个径向渐变效果的最后一个色标都是透明色。如果想要两色标直接的过渡柔和一些,只要两个颜色值一致就可以了。代码里面看不出来,是因为我用了两种不同的颜色表示方法,但其实是相同的,#019F62 = rgba(1,159,98,1)。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); // Create gradients var radgrad = ctx.createRadialGradient(45,45,10,52,50,30); radgrad.addColorStop(0, '#A7D30C'); radgrad.addColorStop(0.9, '#019F62'); radgrad.addColorStop(1, 'rgba(1,159,98,0)'); var radgrad2 = ctx.createRadialGradient(105,105,20,112,120,50); radgrad2.addColorStop(0, '#FF5F98'); radgrad2.addColorStop(0.75, '#FF0188'); radgrad2.addColorStop(1, 'rgba(255,1,136,0)'); var radgrad3 = ctx.createRadialGradient(95,15,15,102,20,40); radgrad3.addColorStop(0, '#00C9FF'); radgrad3.addColorStop(0.8, '#00B5E2'); radgrad3.addColorStop(1, 'rgba(0,201,255,0)'); var radgrad4 = ctx.createRadialGradient(0,150,50,0,140,90); radgrad4.addColorStop(0, '#F4F201'); radgrad4.addColorStop(0.8, '#E4C700'); radgrad4.addColorStop(1, 'rgba(228,199,0,0)'); // draw shapes ctx.fillStyle = radgrad4; ctx.fillRect(0,0,150,150); ctx.fillStyle = radgrad3; ctx.fillRect(0,0,150,150); ctx.fillStyle = radgrad2; ctx.fillRect(0,0,150,150); ctx.fillStyle = radgrad; ctx.fillRect(0,0,150,150); }
图案 Patterns
上一节的一个例子里面,我用了循环来实现图案的效果。其实,有一个更加简单的方法:createPattern。
createPattern(image,type)
该方法接受两个参数。Image 可以是一个Image对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeat,repeat-x,repeat-y
和no-repeat。图案的应用跟渐变很类似的,创建出一个 pattern 之后,赋给fillStyle或strokeStyle属性即可。
var img = new Image(); img.src = 'someimage.png'; var ptrn = ctx.createPattern(img,'repeat');
注意:与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。Firefox 目前只支持属性值repeat。如果赋其它值,什么效果都没有的。
createPattern
的例子
这最后的例子,我创建一个图案然后赋给了fillStyle属性。值得一提的是,使用 Image 对象的onloadhandler 来确保设置图案之前图像已经装载完毕。
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); // create new image object to use as pattern var img = new Image(); img.src = 'images/wallpaper.png'; img.onload = function(){ // create pattern var ptrn = ctx.createPattern(img,'repeat'); ctx.fillStyle = ptrn; ctx.fillRect(0,0,150,150); } }
以上就是canvas游戏开发学习之六:运用样式与颜色(二)的内容,更多相关内容请关注PHP中文网(www.php.cn)!