上一篇讲了如何用canvas绘制简单的图形曲线等,也在图形中加了颜色等。这一篇主要讲下如何添加样式和颜色。
色彩
fillStyle
设置图形的填充颜色,fillStyle = color,color可以表示css颜色值的字符串、渐变对象或者图案对象。1
2
3
4
5// 这些 fillStyle 的值均为 '橙色'
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255,165,0)";
ctx.fillStyle = "rgba(255,165,0,1)";
fillStyle示例:
See the Pen RMJJJV by LCINA (@LCINA) on CodePen.
strokeStyle
设置图形轮廓的颜色,strokeStyle = color,这里color的表示跟fillStyle一致。
注意: 一旦您设置了 strokeStyle 或者 fillStyle 的值,那么这个新值就会成为新绘制的图形的默认值。如果你要给每个图形上不同的颜色,你需要重新设置 fillStyle 或 strokeStyle 的值。
strokeStyle示例:
See the Pen rdKKZX by LCINA (@LCINA) on CodePen.
透明度
globalAlpha属性,可以设置图形透明度,根据直译,该属性用来设置全局图形透明,但是在此属性之前定义的图形透明度不受其影响。对于单个图形透明度的设置,可以根据css3颜色值,设置具有透明度的颜色。1
2
3// 指定透明颜色,用于描边和填充样式
ctx.strokeStyle = "rgba(255,0,0,0.5)";
ctx.fillStyle = "rgba(255,0,0,0.5)";
globalAlpha 示例:
See the Pen LdrBPx by LCINA (@LCINA) on CodePen.
线型
lineWidth
根据属性名就可以知道该属性用来设置线段的粗细,默认值为1,且必须为正数。
线宽是指给定路径的中心到两边的粗细。换句话说就是在路径的两边各绘制线宽的一半。因为画布的坐标并不和像素直接对应,当需要获得精确的水平或垂直线的时候要特别注意。MDN文档中用一个例子,讲了这个问题。
See the Pen wmXxrO by LCINA (@LCINA) on CodePen.
从上面例子可以发现,所有宽度为奇数的线段边缘看起来有点失真,不能精确呈现,这是因为路径的定位问题。
用网格来代表 canvas 的坐标格,每一格对应屏幕上一个像素点。在第一个图中,填充了 (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 图形时会有点小痛苦,但是及早注意到像素网格与路径位置之间的关系,可以确保图形在经过缩放或者其它任何变形后都可以保持看上去蛮好:线宽为 1.0 的垂线在放大 2 倍后,会变成清晰的线宽为 2.0,并且出现在它应该出现的位置上。
lineCap
该属性决定了线段端点显示的样式。包含3个属性值:butt,round 和 square。默认是butt。
See the Pen geKjEE by LCINA (@LCINA) on CodePen.
最左边的线用了默认的 butt 。可以注意到它是与辅助线齐平的。中间的是 round 的效果,端点处加上了半径为一半线宽的半圆。右边的是 square 的效果,端点处加上了等宽且高度为一半线宽的方块。
lineJoin
该属性决定了图形中两线段连接处所显示的样子。包含3个属性值:round, bevel 和 miter。默认是miter。
See the Pen OvEwKK by LCINA (@LCINA) on CodePen.
同样用三条折线来做例子,分别设置不同的 lineJoin 值。最上面一条是 round 的效果,边角处被磨圆了,圆的半径等于线宽。中间和最下面一条分别是 bevel 和 miter 的效果。当值是 miter 的时候,线段会在连接处外侧延伸直至交于一点,延伸效果受到下面将要介绍的 miterLimit 属性的制约。
使用虚线
用 setLineDash 方法和 lineDashOffset 属性来制定虚线样式。setLineDash 方法接受一个数组,来指定线段与间隙的交替;lineDashOffset 属性设置起始偏移量。
See the Pen rdKZaz by LCINA (@LCINA) on CodePen.
渐变
用线性或者径向的渐变来填充或描边。
线性渐变
createLinearGradient(x1, y1, x2, y2),createLinearGradient 方法接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)。
1 | var lineargradient = ctx.createLinearGradient(0,0,150,150); |
径向渐变
createRadialGradient(x1, y1, r1, x2, y2, r2),createRadialGradient 方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。
1 | var radialgradient = ctx.createRadialGradient(75,75,0,75,75,100); |
addColorStop
gradient.addColorStop(position, color),addColorStop 方法接受 2 个参数,position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。color 参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)。
See the Pen wmXEgK by LCINA (@LCINA) on CodePen.
图案样式
createPattern(image, type),该方法接受两个参数。Image 可以是一个 Image 对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeat,repeat-x,repeat-y 和 no-repeat。1
2
3var img = new Image();
img.src = 'someimage.png';
var ptrn = ctx.createPattern(img,'repeat');
注意:与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。
阴影
shadowOffsetX = floatshadowOffsetY = floatshadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0。
shadowBlur = float
shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0。
shadowColor = color
shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。
See the Pen yKEQem by LCINA (@LCINA) on CodePen.
Canvas 填充规则
当我们用到 fill(或者 clip和isPointinPath )你可以选择一个填充规则,该填充规则根据某处在路径的外面或者里面来决定该处是否被填充,这对于自己与自己路径相交或者路径被嵌套的时候是有用的。
See the Pen QmxJEP by LCINA (@LCINA) on CodePen.
参考资料:
使用样式和颜色