运用样式与颜色

绘制图形 的章节里,我只用到默认的线条和填充样式。而在这一章里,我们将会探讨 canvas 全部的可选项,来绘制出更加吸引人的内容。

色彩 Colors

Up until now we've only seen methods of the drawing context. If we want to apply colors to a shape, there are two important properties we can use: fillStyle and strokeStyle.

到目前为止,我们只看到过绘制内容的方法。如果我们想要给图形上色,有两个重要的属性可以做到:fillStyle strokeStyle。

fillStyle = color
strokeStyle = color

strokeStyle is used for setting the shape outline color and fillStyle is for the fill color. color can be a string representing a CSS color value, a gradient object, or a pattern object. We'll look at gradient and pattern objects later. By default, the stroke and fill color are set to black (CSS color value #000000).

strokeStyle 是用于设置图形轮廓的颜色,而 fillStyle 用于设置填充颜色。color 可以是表示 CSS 颜色值的字符串,渐变对象或者图案对象。我们迟些再回头探讨渐变和图案对象。默认情况下,线条和填充颜色都是黑色(CSS 颜色值 #000000)。

The valid strings you can enter should, according to the specification, be CSS3 color values. Each of the following examples describe the same color.

您输入的应该是符合 CSS3 颜色值标准 的有效字符串。下面的例子都表示同一种颜色。

// 这些 fillStyle 的值均为 '橙色'
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255,165,0)";
ctx.fillStyle = "rgba(255,165,0,1)";

Note: Currently not all CSS 3 color values are supported in the Gecko engine. For instance the color values hsl(100%,25%,0) or rgb(0,100%,0) are not allowed. If you stick to the ones above, you won't run into any problems.

注意: 目前 Gecko 引擎并没有提供对所有的 CSS 3 颜色值的支持。例如,hsl(100%,25%,0) 或者 rgb(0,100%,0) 都不可用。但如果您遵循上面例子的规范,应该不会有问题。

Note: If you set the strokeStyle and/or fillStyle property, the new value becomes the default for all shapes being drawn from then on. For every shape you want in a different color, you will need to reassign the fillStyle or strokeStyle property.

注意: 一旦您设置了 strokeStyle 或者 fillStyle 的值,那么这个新值就会成为新绘制的图形的默认值。如果你要给每个图形上不同的颜色,你需要重新设置 fillStylestrokeStyle 的值。

fillStyle 示例

In this example, I once again use two for loops to draw a grid of rectangles, each in a different color. The resulting image should look something like the image on the right. There is nothing too spectacular happening here. I use the two variables i and j to generate a unique RGB color for each square. I only modify the red and green values. The blue channel has a fixed value. By modifying the channels, you can generate all kinds of palettes. By increasing the steps, you can achieve something that looks like the color palettes Photoshop uses.

在本示例里,我会再度用两层 for 循环来绘制方格阵列,每个方格不同的颜色。结果如右图,但实现所用的代码却没那么绚丽。我用了两个变量 i 和 j 来为每一个方格产生唯一的 RGB 色彩值,其中仅修改红色和绿色通道的值,而保持蓝色通道的值不变。你可以通过修改这些颜色通道的值来产生各种各样的色板。通过增加渐变的频率,你还可以绘制出类似 Photoshop 里面的那样的调色板。

查看示例

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  for (var i=0;i<6;i++){
    for (var j=0;j<6;j++){
      ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' + 
                       Math.floor(255-42.5*j) + ',0)';
      ctx.fillRect(j*25,i*25,25,25);
    }
  }
}

strokeStyle 示例

This example is similar to the one above but now using the strokeStyle property. Here I use the arc method to draw circles instead of squares.

这个示例与上面的有点类似,但这次用到的是 strokeStyle 属性,画的不是方格,而是用 arc 方法来画圆。

查看示例

  function draw() {
    var ctx = document.getElementById('canvas').getContext('2d');
    for (var i=0;i<6;i++){
      for (var j=0;j<6;j++){
        ctx.strokeStyle = 'rgb(0,' + Math.floor(255-42.5*i) + ',' + 
                         Math.floor(255-42.5*j) + ')';
        ctx.beginPath();
        ctx.arc(12.5+j*25,12.5+i*25,10,0,Math.PI*2,true);
        ctx.stroke();
      }
    }
  }

透明度 Transparency

Besides drawing opaque shapes to the canvas, we can also draw semi-transparent shapes. This is done by setting the globalAlpha property, or we could assign a semi-transparent color to the stroke and/or fill style.

除了可以绘制实色图形,我们还可以用 canvas 来绘制半透明的图形。通过设置 globalAlpha 属性或者使用一个半透明颜色作为轮廓或填充的样式。

globalAlpha = transparency value

This property applies a transparency value to all shapes drawn on the canvas. The valid range of values is from 0.0 (fully transparent) to 1.0 (fully opaque). By default, this property is set to 1.0 (fully opaque).

这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。

The globalAlpha property can be useful if you want to draw a lot of shapes on the canvas with similar transparency. I think, however, that the next option is a little more practical.

globalAlpha 属性在需要绘制大量拥有相同透明度的图形时候相当高效。不过,我认为下面的方法可操作性更强一点。

Because the strokeStyle and fillStyle properties accept CSS 3 color values, we can use the following notation to assign a transparent color to them.

因为 strokeStylefillStyle 属性接受符合 CSS 3 规范的颜色值,那我们可以用下面的写法来设置具有透明度的颜色。

// Assigning transparent colors to stroke and fill style
ctx.strokeStyle = "rgba(255,0,0,0.5)";
ctx.fillStyle = "rgba(255,0,0,0.5)";

The rgba() function is similar to the rgb() function but it has one extra parameter. The last parameter sets the transparency value of this particular color. The valid range is again between 0.0 (fully transparent) and 1.0 (fully opaque).

rgba() 方法与 rgb() 方法类似,就多了一个用于设置色彩透明度的参数。它的有效范围是从 0.0(完全透明)到 1.0(完全不透明)。

globalAlpha 示例

In this example I've drawn a background of four different colored squares. On top of these, I've draw a set of semi-transparent circles. The globalAlpha property is set at 0.2 which will be used for all shapes from that point on. Every step in the for loop draws a set of circles with an increasing radius. The final result is a radial gradient. By overlaying ever more circles on top of each other, we effectively reduce the transparency of the circles that have already been drawn. By increasing the step count and in effect drawing more circles, the background would completely disappear from the center of the image.

在这个例子里,我用四色格作为背景,设置 globalAlpha 为 0.2后,在上面画一系列半径递增的半透明圆。最终结果是一个径向渐变效果。圆叠加得越更多,原先所画的圆的透明度会越低。通过增加循环次数,画更多的圆,背景图的中心部分会完全消失。

注意:
  • 这个例子在 Firefox 1.5 beta 1 里是行不通的。你需要 nightly branch build 或者等待新版本发布来实践这个效果。
  • 这个例子在 Safari 下可能由于颜色值无效而达不到效果。例子里是 '#09F' 是不符合规范要求的,不过 Firefox 是认识这种格式的。

查看示例

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  // draw background
  ctx.fillStyle = '#FD0';
  ctx.fillRect(0,0,75,75);
  ctx.fillStyle = '#6C0';
  ctx.fillRect(75,0,75,75);
  ctx.fillStyle = '#09F';
  ctx.fillRect(0,75,75,75);
  ctx.fillStyle = '#F30';
  ctx.fillRect(75,75,75,75);
  ctx.fillStyle = '#FFF';

  // set transparency value
  ctx.globalAlpha = 0.2;

  // Draw semi transparent circles
  for (var i=0;i<7;i++){
      ctx.beginPath();
      ctx.arc(75,75,10+10*i,0,Math.PI*2,true);
      ctx.fill();
  }
}

rgba()示例

In this second example I've done something similar to the one above, but instead of drawing circles on top of each other, I've drawn small rectangles with increasing opacity. Using rgba() gives you a little more control and flexibility because we can set the fill and stroke style individually.

第二个例子和上面那个类似,不过不是画圆,而是画矩形。这里还可以看出,rgba() 可以分别设置轮廓和填充样式,因而具有更好的可操作性和使用弹性。

查看示例

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  // Draw background
  ctx.fillStyle = 'rgb(255,221,0)';
  ctx.fillRect(0,0,150,37.5);
  ctx.fillStyle = 'rgb(102,204,0)';
  ctx.fillRect(0,37.5,150,37.5);
  ctx.fillStyle = 'rgb(0,153,255)';
  ctx.fillRect(0,75,150,37.5);
  ctx.fillStyle = 'rgb(255,51,0)';
  ctx.fillRect(0,112.5,150,37.5);

  // Draw semi transparent rectangles
  for (var i=0;i<10;i++){
    ctx.fillStyle = 'rgba(255,255,255,'+(i+1)/10+')';
    for (var j=0;j<4;j++){
      ctx.fillRect(5+i*14,5+j*37.5,14,27.5)
    }
  }
}

线型 Line styles

There are several properties which allow us to style lines.

可以通过一系列属性来设置线的样式。

lineWidth = value
lineCap = type
lineJoin = type
miterLimit = value

I could describe these in detail, but it will probably be made clearer by just looking at the examples below.

我会详细介绍这些属性,不过通过以下的样例可能会更加容易理解。

lineWidth 属性的例子

This property sets the current line thickness. Values must be positive numbers. By default this value is set to 1.0 units.

这个属性设置当前绘线的粗细。属性值必须为正数。默认值是1.0。

The line width is the thickness of the stroke centered on the given path. In other words, the area that's drawn extends to half the line width on either side of the path. Because canvas coordinates do not directly reference pixels, special care must be taken to obtain crisp horizontal and vertical lines.

线宽是指给定路径的中心到两边的粗细。换句话说就是在路径的两边各绘制线宽的一半。因为画布的坐标并不和像素直接对应,当需要获得精确的水平或垂直线的时候要特别注意。

In the example below, 10 straight lines are drawn with increasing line widths. The line on the far left is 1.0 units wide. However, the leftmost and all other odd-integer-width thickness lines do not appear crisp, because of the path's positioning.

在下面的例子中,用递增的宽度绘制了10条直线。最左边的线宽1.0单位。并且,最左边的以及所有宽度为奇数的线并不能精确呈现,这就是因为路径的定位问题。

查看示例

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();
  }
}

Obtaining crisp lines requires understanding how paths are stroked. In the images below, the grid represents the canvas coordinate grid. The squares between gridlines are actual on-screen pixels. In the first grid image below, a rectangle from (2,1) to (5,5) is filled. The entire area between them (light red) falls on pixel boundaries, so the resulting filled rectangle will have crisp edges.

想要获得精确的线条,必须对线条是如何描绘出来的有所理解。见下图,用网格来代表 canvas 的坐标格,每一格对应屏幕上一个像素点。在第一个图中,填充了 (2,1) 至 (5,5) 的矩形,整个区域的边界刚好落在像素边缘上,这样就可以得到的矩形有着清晰的边缘。

If you consider a path from (3,1) to (3,5) with a line thickness of 1.0, you end up with the situation in the second image. The actual area to be filled (dark blue) only extends halfway into the pixels on either side of the path. An approximation of this has to be rendered, which means that those pixels being only partially shaded, and results in the entire area (the light blue and dark blue) being filled in with a color only half as dark as the actual stroke color. This is what happens with the 1.0 width line in the previous example code.

如果你想要绘制一条从 (3,1) 到 (3,5),宽度是 1.0 的线条,你会得到像第二幅图一样的结果。实际填充区域(深蓝色部分)仅仅延伸至路径两旁各一半像素。而这半个像素又会以近似的方式进行渲染,这意味着那些像素只是部分着色,结果就是以实际笔触颜色一半色调的颜色来填充整个区域(浅蓝和深蓝的部分)。这就是上例中为何宽度为 1.0 的线并不准确的原因。

To fix this, you have to be very precise in your path creation. Knowing that a 1.0 width line will extend half a unit to either side of the path, creating the path from (3.5,1) to (3.5,5) results in the situation in the third image -- the 1.0 line width ends up completely and precisely filling a single pixel vertical line.

要解决这个问题,你必须对路径施以更加精确的控制。已知粗 1.0 的线条会在路径两边各延伸半像素,那么像第三幅图那样绘制从 (3.5,1) 到 (3.5,5) 的线条,其边缘正好落在像素边界,填充出来就是准确的宽为 1.0 的线条。

For even-width lines, each half ends up being an integer amount of pixels, so you want a path that is between pixels (that is, (3,1) to (3,5)), instead of down the middle of pixels. Also, be aware that in our vertical line example, the Y position still referenced an integer gridline position -- if it hadn't, we would see pixels with half coverage at the endpoints.

对于那些宽度为偶数的线条,每一边的像素数都是整数,那么你想要其路径是落在像素点之间 (如那从 (3,1) 到 (3,5)) 而不是在像素点的中间。同样,注意到那个例子的垂直线条,其 Y 坐标刚好落在网格线上,如果不是的话,端点上同样会出现半渲染的像素点。

While slightly painful when initially working with scalable 2D graphics, paying attention to the pixel grid and the position of paths ensures that your drawings will look correct regardless of scaling or any other transformations involved. A 1.0-width vertical line drawn at the correct position will become a crisp 2-pixel line when scaled up by 2, and will appear at the correct position.

虽然开始处理可缩放的 2D 图形时会有点小痛苦,但是及早注意到像素网格与路径位置之间的关系,可以确保图形在经过缩放或者其它任何变形后都可以保持看上去蛮好:线宽为 1.0 的垂线在放大 2 倍后,会变成清晰的线宽为 2.0,并且出现在它应该出现的位置上。

lineCap 属性的例子

The lineCap property determines how the end points of every line are drawn. There are three possible values for this property and those are: butt, round and square. By default this property is set to butt.

属性 lineCap 的值决定了线段端点显示的样子。它可以为下面的三种的其中之一:buttroundsquare。默认是 butt。

In this example, I've drawn three lines, each with a different value for the lineCap property. I also added two guides to see the exact differences between the three. Each of these lines starts and ends exactly on these guides.

这个例子里面,我绘制了三条直线,分别赋予不同的 lineCap 值。还有两条辅助线,为了可以看得更清楚它们之间的区别,三条线的起点终点都落在辅助线上。

The line on the left uses the default butt option. You'll notice that it's drawn completely flush with the guides. The second is set to use the round option. This adds a semicircle to the end that has a radius half the width of the line. The line on the right uses the square option. This adds a box with an equal width and half the height of the line thickness.

最左边的线用了默认的 butt 。可以注意到它是与辅助线齐平的。中间的是 round 的效果,端点处加上了半径为一半线宽的半圆。右边的是 square 的效果,端点处加上了等宽且高度为一半线宽的方块。

查看示例

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  var lineCap = ['butt','round','square'];

  // Draw guides
  ctx.strokeStyle = '#09f';
  ctx.beginPath();
  ctx.moveTo(10,10);
  ctx.lineTo(140,10);
  ctx.moveTo(10,140);
  ctx.lineTo(140,140);
  ctx.stroke();

  // Draw lines
  ctx.strokeStyle = 'black';
  for (var i=0;i<lineCap.length;i++){
    ctx.lineWidth = 15;
    ctx.lineCap = lineCap[i];
    ctx.beginPath();
    ctx.moveTo(25+i*50,10);
    ctx.lineTo(25+i*50,140);
    ctx.stroke();
  }
}

lineJoin 属性的例子

The lineJoin property determines how two connecting lines in a shape are joined together. There are three possible values for this property: round, bevel and miter. By default this property is set to miter.

lineJoin 的属性值决定了图形中两线段连接处所显示的样子。它可以是这三种之一:round, bevelmiter。默认是 miter

Again I've drawn three different paths, each with a different lineJoin property setting. The top path uses the round option. This setting rounds off the corners of a shape. The radius for these rounded corners is equal to the line width. The second line uses the bevel option and the line at the bottom uses the miter option. When set to miter, lines are joined by extending the outside edges to connect at a single point. This setting is effected by the miterLimit property which is explained below.

这里我同样用三条折线来做例子,分别设置不同的 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 属性的演示例子

As you've seen in the previous example, when joining two lines with the miter option, the outside edges of the two joining lines are extended up to the point where they meet. For lines which are at large angles with each other, this point is not far from the inside connection point. However, when the angles between each line decreases, the distance (miter length) between these points increases exponentially.

就如上一个例子所见的应用 miter 的效果,线段的外侧边缘会延伸交汇于一点上。线段直接夹角比较大的,交点不会太远,但当夹角减少时,交点距离会呈指数级增大。

The miterLimit property determines how far the outside connection point can be placed from the inside connection point. If two lines exceed this value, a bevel join will be drawn.

miterLimit 属性就是用来设定外延交点与连接点的最大距离,如果交点距离大于此值,连接效果会变成了 bevel。

I've made a little demo in which you can set miterLimit dynamically and see how this effects the shapes on the canvas. The blue lines show where the start and endpoints for each of the lines in the zig-zag pattern are.

我做了一个演示页面,你可以动手改变 miterLimit 的值,观察其影响效果。蓝色辅助线显示锯齿折线段的起点与终点所在的位置。

去看看演示

渐变 Gradients

Just like any normal drawing program, we can fill and stroke shapes using linear and radial gradients. We create a canvasGradient object by using one of the following methods. We use this object to assign it to the fillStyle or strokeStyle properties.

就好像一般的绘图软件一样,我们可以用线性或者径向的渐变来填充或描边。我们用下面的方法新建一个 canvasGradient 对象,并且赋给图形的 fillStylestrokeStyle 属性。

createLinearGradient(x1,y1,x2,y2)
createRadialGradient(x1,y1,r1,x2,y2,r2)

The createLinearGradient method takes four arguments representing the starting point (x1,y1) and end point (x2,y2) of the gradient.
The createRadialGradient method takes six arguments. The first three arguments define a circle with coordinates (x1,y1) and radius r1 and the second a circle with coordinates (x2,y2) and radius 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);

Once we've created a canvasGradient object we can assign colors to it by using the addColorStop method.

创建出 canvasGradient 对象后,我们就可以用 addColorStop 方法给它上色了。

addColorStop(position, color)

This method takes two arguments. The position must be a number between 0.0 and 1.0 and defines the relative position of the color in the gradient. Setting this to 0.5 for instance would place the color precisely in the middle of the gradient. The color argument must be a string representing a CSS color (ie #FFF, rgba(0,0,0,1),etc).

addColorStop 方法接受 2 个参数,position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。color 参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)。

You can add as many color stops to a gradient as you need. Below is a very simple linear gradient from white to black.

你可以根据需要添加任意多个色标(color stops)。下面是最简单的线性黑白渐变的例子。

var lineargradient = ctx.createLinearGradient(0,0,150,150);
lineargradient.addColorStop(0,'white');
lineargradient.addColorStop(1,'black');

createLinearGradient 的例子

In this example, I've created two different gradients. In the first, I create the background gradient. As you can see, I've assigned two colors at the same position. You do this to make very sharp color transitions - in this case from white to green. Normally, it doesn't matter in what order you define the color stops, but in this special case, it does significantly. If you keep the assignments in the order you want them to appear, this won't be a problem.

本例中,我弄了两种不同的渐变。第一种是背景色渐变,你会发现,我给同一位置设置了两种颜色,你也可以用这来实现突变的效果,就像这里从白色到绿色的突变。一般情况下,色标的定义是无所谓顺序的,但是色标位置重复时,顺序就变得非常重要了。所以,保持色标定义顺序和它理想的顺序一致,结果应该没什么大问题。

In the second gradient, I didn't assign the starting color (at position 0.0) since it wasn't strictly necessary. Assigning the black color at position 0.5 automatically makes the gradient, from the start to this stop, black.

第二种渐变,我并不是从 0.0 位置开始定义色标,因为那并不是那么严格的。在 0.5 处设一黑色色标,渐变会默认认为从起点到色标之间都是黑色。

As you can see here, both the strokeStyle and fillStyle properties can accept a canvasGradient object as valid input.

你会发现,strokeStylefillStyle 属性都可以接受 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 的例子

In this example, I've defined four different radial gradients. Because we have control over the start and closing points of the gradient, we can achieve more complex effects than we would normally have in the 'classic' radial gradients we see in, for instance, Photoshop. (i.e. a gradient with a single center point where the gradient expands outward in a circular shape.)

这个例子,我定义了 4 个不同的径向渐变。由于可以控制渐变的起始与结束点,所以我们可以实现一些比(如在 Photoshop 中所见的)经典的径向渐变更为复杂的效果。(经典的径向渐变是只有一个中心点,简单地由中心点向外围的圆形扩张)

In this case, I've offset the starting point slightly from the end point to achieve a spherical 3D effect. It's best to try to avoid letting the inside and outside circles overlap because this results in strange effects which are hard to predict.

这里,我让起点稍微偏离终点,这样可以达到一种球状 3D 效果。但最好不要让里圆与外圆部分交叠,那样会产生什么效果就真是不得而知了。

The last color stop in each of the four gradients uses a fully transparent color. If you want to have a nice transition from this to the previous color stop, both colors should be equal. This isn't very obvious from the code because I've used two different CSS color methods, but in the first gradient #019F62 = rgba(1,159,98,1)

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

In one of the examples on the previous page, I used a series of loops to create a pattern of images. There is, however, a much simpler method: the createPattern method.

上一节的一个例子里面,我用了循环来实现图案的效果。其实,有一个更加简单的方法:createPattern。

createPattern(image,type)

This method takes two arguments. Image is either a reference to an Image object or a different canvas element. Type must be a string containing one of the following values: repeat, repeat-x, repeat-y and no-repeat.

该方法接受两个参数。Image 可以是一个 Image 对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeatrepeat-xrepeat-yno-repeat

注意: 用 canvas 对象作为 Image 参数在 Firefox 1.5 (Gecko 1.8) 中是无效的。

We use this method to create a Pattern object which is very similar to the gradient methods we've seen above. Once we've created a pattern, we can assign it to the fillStyle or strokeStyle properties.

图案的应用跟渐变很类似的,创建出一个 pattern 之后,赋给 fillStylestrokeStyle 属性即可。

var img = new Image();
img.src = 'someimage.png';
var ptrn = ctx.createPattern(img,'repeat');

Note: Unlike the drawImage method, you must make sure the image you use is loaded before calling this method or the pattern may be drawn incorrectly.

注意:与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。

Note: Firefox currently only supports the repeat property. If you assign anything else, you won't see any changes.

注意:Firefox 目前只支持属性值repeat 。如果赋其它值,什么效果都没有的。

createPattern 的例子

In this last example, I created a pattern which I assigned to the fillStyle property. The only thing worth noting is the use of the Image object onload handler. This is to make sure the image is loaded before it is assigned to the pattern.

这最后的例子,我创建一个图案然后赋给了 fillStyle 属性。值得一提的是,使用 Image 对象的 onload handler 来确保设置图案之前图像已经装载完毕。

查看示例

Source image

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);

  }
}

阴影 Shadows

Firefox 3.5 (Gecko 1.9.1) introduced support for shadows in canvases.  Using shadows involves just four properties:

Firefox 3.5 (Gecko 1.9.1) 在 canvas 中加入了对阴影的支持,就 4 个属性。

shadowOffsetX = float
shadowOffsetY = float
shadowBlur = float
shadowColor = color

shadowOffsetX and shadowOffsetY indicate how far the shadow should extend from the object in the X and Y directions; these values aren't affected by the current transformation matrix.  Use negative values to cause the shadow to extend up or to the left, and positive values to cause the shadow to extend down or to the right.  These are both 0 by default.

shadowOffsetX shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,他们默认都是 0。

shadowBlur indicates the size of the blurring effect; this value doesn't correspond to a number of pixels and is not affected by the current transformation matrix.  The default value is 0.

shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0。

shadowColor is a standard CSS color value indicating the color of the shadow effect; by default, it is fully-transparent black.

shadowColor 用于设定阴影效果的延伸,值可以是标准的 CSS 颜色值,默认是全透明的黑色。

文字阴影的例子

This example draws a text string with a shadowing effect.

这个例子绘制了带阴影效果的文字。

查看示例

Source image

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  ctx.shadowOffsetX = 2;
  ctx.shadowOffsetY = 2;
  ctx.shadowBlur = 2;
  ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
 
  ctx.font = "20px Times New Roman";
  ctx.fillStyle = "Black";
  ctx.fillText("Sample String", 5, 30);
}

附件

文件 大小 日期 附加者为
canvas-grid.png
7729 字节 2007-10-11 20:14:14 VladVukicevic
Canvas_createpattern.png
21987 字节 2005-10-02 17:56:31 KamielMartinet
Canvas_fillstyle.png
914 字节 2005-09-17 17:19:54 KamielMartinet
Canvas_globalalpha.png
7432 字节 2005-09-18 13:36:10 KamielMartinet
Canvas_lineargradient.png
1582 字节 2005-10-01 10:53:05 KamielMartinet
Canvas_linecap.png
1410 字节 2005-09-20 17:08:08 KamielMartinet
Canvas_linejoin.png
2419 字节 2005-09-20 18:27:46 KamielMartinet
Canvas_linewidth.png
871 字节 2005-09-20 16:58:07 KamielMartinet
Canvas_miterlimit.png
6452 字节 2005-09-30 18:28:29 KamielMartinet
Canvas_radialgradient.png
13230 字节 2005-10-01 10:54:38 KamielMartinet
Canvas_rgba.png
1182 字节 2005-09-19 17:11:23 KamielMartinet
Canvas_strokestyle.png
13274 字节 2005-09-18 09:33:37 KamielMartinet
shadowed-string.png
5077 字节 2008-10-01 21:11:25 Sheppy
shadowed-text.html
1638 字节 2008-10-01 20:59:34 Sheppy
B6mvo1ci.jpg
4005 字节 2007-09-02 14:07:37 Tha-killer
Flag_of_Portugal.gif
3822 字节 2007-08-26 15:46:55 Jorge100
Foto.6.BMP
57654 字节 2007-10-26 15:40:19 Zara
Johnny_Cash_-_I_Walk_The_Line.mp3
2617580 字节 2007-12-26 11:31:49 Zooroo
Just_enjoying.jpg
15035 字节 2007-07-02 19:23:22 Oldskool67
Mininova_Search.zip
626 字节 2007-10-31 20:01:28 Badboystar
NovaNutria.jpg
5364 字节 2008-01-23 16:15:23 Wahidj
Resident_Evil_Umbrella_Wallpaper.jpg
91435 字节 2007-06-28 20:00:58 Umbrella
Vrijgezel12.jpg
54886 字节 2007-12-01 22:25:53 Annekeverschave
01pswd.gif
3780 字节 2005-10-31 15:27:34 Prometeo
16chver.gif
7514 字节 2005-10-31 15:29:03 Prometeo
pluralForm-checker.png
76764 字节 2008-01-27 17:30:05 Mardak
repeating_linear_gradient.png
3404 字节 2009-12-04 22:59:08 Sheppy
repeating_radial_gradient.png
3789 字节 2009-12-04 22:59:10 Sheppy

Document Tags and Contributors

Contributors to this page: 吕辛未, zhongsheng, leegorous, Uliyas_Fan, Chinese_XU, Qq759
最后编辑者: Uliyas_Fan,