本节书摘来自异步社区《HTML5 Canvas开发详解》一书中的第2章,第2.8节,作者: 【美】Steve Fulton , Jeff Fulton 更多章节内容可以访问云栖社区“异步社区”公众号查看。
2.8 用颜色和渐变填充对象
本章已经在讨论创建基本和复杂形状时,粗略地介绍了颜色和填充样式。本节将深入探讨形状的着色和填充。除了这些简单的着色和填充外,还有很多可用的不同渐变样式。另外,Canvas还可以使用位图来填充形状(参见第4章)。
2.8.1 基本填充颜色设置
Canvas fillStyle属性用来设置画布上形状的基本颜色和填充,fillStyle使用简单的颜色名称,这看起来非常简单。例如:
context.fillStyle = "red";
下面是出自HTML4规范的可用颜色字符串值列表。截止到写作这些内容为止,HTML5没有对此另行设定。由于没有增加HTML5专属的颜色,HTML4的颜色都可以在HTML5中正确显示。
黑色 Black = #000000
绿色 Green = #008000
银色 Silver = #C0C0C0
石灰色 Lime = #00FF00
灰色 Gray = #808080
橄榄色 Olive = #808000
白色 White = #FFFFFF
黄色 Yellow = #FFFF00
栗色 Maroon = #800000
海蓝色 Navy = #000080
红色 Red = #FF0000
蓝色 Blue = #0000FF
紫色 Purple = #800080
深蓝绿色 Teal = #008080
紫红色 Fuchsia = #FF00FF
浅蓝绿色 Aqua = #00FFFF
提示:
所有这些颜色值都可以应用到strokeStyle和fillStyle中。
当然,使用颜色名称字符串并不是指定一个纯填充的唯一方法,以下是其他一些方法。
(1)以rgb()方法设置填充色。
rgb()方法可以用24位RGB值指定填充色。
context.fillStyle = rgb(255,0,0);
这与上面使用red字符串设定的红色是一样的。
(2)以十六进制数字字符串设置填充色
也可以使用一个十六进制数字字符串设置fillStyle颜色。
context.fillStyle = "#ff0000";
(3)以rgba()方法设置填充色。
rgba()方法可以指定32位色值的填充色,其后8位表示透明度。
context.fillStyle = rgba(255,0,0,1);
透明度范围从1(不透明)到0(透明)。
2.8.2 填充渐变形状
在画布上创建渐变填充有两个基本选项:线性或者径向。线性渐变创建一个水平、垂直或者对角线的填充图案。径向渐变自中心点创建一个放射状填充。下面是它们的一些示例。
线性渐变
线性渐变有3种基本样式:水平、垂直和对角线。通过沿对象设置的颜色断点来控制渐变颜色。例2-14为创建一个简单水平渐变,如图2-23所示。
例2-14 线性水平渐变
function drawScreen(){
// 水平渐变值必须保持为0
var gr = context.createLinearGradient(0, 0, 100, 0);
// 添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
// 应用fillStyle生成渐变
context.fillStyle = gr;
context.fillRect(0, 0,100,100);
}
创建一个水平渐变,必须首先创建一个变量(gr)来指代一个新的渐变,设置方式如下。
var gr = context.createLinearGradient(0,0,100,0);
createLinearGradient方法调用中的4个值是开始渐变的左上角的x和y坐标,以及结束渐变的右下角的x和y坐标。示例从(0,0)开始到(100,0)结束。请注意,当创建一个水平渐变的时候y值都是0,创建垂直渐变的时候正好相反。
一旦定义了渐变的大小,这里需要使用两个参数值来加入颜色断点。第一个是相对位置的开始渐变颜色的渐变原点,第二个是渐变的颜色。相对位置的值必须在0.0和1.0之间。
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
在例2-14中设置的渐变是起点(0)为红色、中心点(0.5)为绿色、终点(1)为红色,这将填充一个红—绿—红渐变形状。
接下来,应用context.fillStyle生成刚创建的渐变。
context.fillStyle = gr;
最后,在画布上创建一个矩形。
context.fillRect(0, 0, 100, 100);
请注意,刚刚创建了一个与渐变大小完全一样的矩形。这里还可以改变输出矩形的大小,方法如下。
context.fillRect(0, 100, 50, 100);
context.fillRect(0, 200, 200, 100);
例2-15在例2-14的基础上增加了两个新的填充矩形,如图2-24所示。请注意渐变填充满可用空间,最终的颜色填充的区域比定义的渐变区域要大。
https://yqfile.alicdn.com/de2dfd24cc5b694ecdfe8b19069bbbe659ce7831.png" >
例2-15 多个渐变填充对象
function drawScreen(){
var gr = context.createLinearGradient(0, 0, 100, 0);
// 添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
// 应用fillStyle生成渐变
context.fillStyle = gr;
context.fillRect(0, 0, 100, 100);
context.fillRect(0, 100, 50, 100);
context.fillRect(0, 200, 200, 100);
}
渐变可以应用到任何形状,甚至是形状边框。例2-16使用例2-15中的填充矩形创建了一个strokeRect形状,而不是填充矩形。图2-25显示不同的结果。
例2-16 水平描边渐变
function drawScreen(){
var gr = context.createLinearGradient(0, 0, 100, 0);
// 添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
// 将水平渐变应用到描边
// 应用fillStyle生成渐变
context.strokeStyle = gr;
context.strokeRect(0, 0, 100, 100);
context.strokeRect(0, 100, 50, 100);
context.strokeRect(0, 200, 200, 100);
}
https://yqfile.alicdn.com/db5b33da2a6e05ba92839799dfcbab27a472a9fc.png" >
读者也可以将线性渐变应用到由点组成的封闭形状,如例2-17所示。如果形状的起止点相同就是封闭的。
例2-17 复杂形状水平渐变
function drawScreen(){
var gr = context.createLinearGradient(0, 0, 100, 0);
//添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
// 应用fillStyle生成渐变
context.fillStyle = gr;
context.beginPath();
context.moveTo(0,0);
context.lineTo(50,0);
context.lineTo(100,50);
context.lineTo(50,100);
context.lineTo(0,100);
// 将水平渐变应用到复杂形状
context.lineTo(0,0);
context.stroke();
context.fill();
context.closePath();
}
例2-17使用context.fill()命令将当前的fillStyle填充到形状中,输出效果如图2-26所示。
https://yqfile.alicdn.com/5a4078c93d7ec1f507201e4a9584d1f0567199d7.png" >
图2-26显示了通过点创建的新形状,只要点是封闭的,填充就会按需要呈现。
垂直渐变与水平渐变的创建方式非常类似。不同点在于y值不全是0,而x值必须全是0。例2-18显示了例2-17中创建的水平渐变形状显示为垂直渐变的情况,输出结果如图2-27所示。
例2-18 垂直渐变
function drawScreen(){
var gr = context.createLinearGradient(0, 0, 0, 100);
//添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
// 应用fillStyle生成渐变
context.fillStyle = gr;
context.beginPath();
context.moveTo(0,0);
context.lineTo(50,0);
context.lineTo(100,50);
context.lineTo(50,100);
context.lineTo(0,100);
context.lineTo(0,0);
//context.stroke();
context.fill();
context.closePath();
}
例2-18和例2-17的唯一不同在于创建线性渐变的线。
水平渐变(例2-17)如下所示。
var gr = context.createLinearGradient(0, 0, 100, 0);
垂直渐变(例2-18)如下所示。
var gr = context.createLinearGradient(0, 0, 0, 100);
形状边框水平渐变的规则同样适用于垂直渐变。例2-19将例2-18中的形状从填充改成描边,边框效果如图2-28所示。
例2-19 垂直渐变描边
function drawScreen(){
var gr = context.createLinearGradient(0, 0, 0, 100);
//添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
//应用fillStyle生成渐变
context.strokeStyle = gr;
context.beginPath();
context.moveTo(0,0);
context.lineTo(50,0);
context.lineTo(100,50);
context.lineTo(50,100);
context.lineTo(0,100);
context.lineTo(0,0);
context.stroke();
context.closePath();
}
https://yqfile.alicdn.com/7207dbd6d18c164c2fdcff3d3b05848439bfa8b8.png" >
对角线渐变。读者可以轻松创建一个对角线渐变,只需修改createLinearGradient()函数的第二个x和y值。
var gr= context.createLinearGradient(0, 0, 100, 100);
为创建一个如图2-29所示的完美对角线渐变,可以填充一个与对角线渐变相同大小的正方形。代码如例2-20所示。
例2-20 对角线渐变
function drawScreen(){
var gr = context.createLinearGradient(0, 0, 100, 100);
//添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
//应用fillStyle生成渐变
context.fillStyle = gr;
context.beginPath();
context.moveTo(0,0);
context.fillRect(0,0,100,100)
context.closePath();
}
径向渐变
径向渐变的定义过程和线性渐变非常类似。尽管径向渐变需要6个参数设置而线性渐变仅需4个,它同样采用颜色断点的概念来创建颜色变化。
6个参数用来定义两个圆的圆心和半径。第一个圆是开始圈,第二个圆是结束圈。举例如下。
var gr = context.createRadialGradient(50,50,25,50,50,100);
第一个圆的圆心位于(50,50),半径为25;第二个圆的圆心位于(50,50),半径为100。
这将会创建两个同心圆,然后向线性渐变那样设置颜色断点。
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
例2-21将这些代码合并起来,结果如图2-30所示。
例2-21 简单径向渐变
function drawScreen(){
var gr = context.createRadialGradient(50,50,25,50,50,100);
//添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
//应用fillStyle生成渐变
context.fillStyle = gr;
context.fillRect(0, 0, 200, 200);
}
https://yqfile.alicdn.com/9e29eb6e6dc0698828ecf836fcfe7b1ff2dd317d.png" >
例2-22将第二个圆远离第一个圆,产生的效果如图2-31所示。
例2-22 复杂径向渐变
function drawScreen(){
var gr = context.createRadialGradient(50,50,25,100,100,100);
//添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
//应用fillStyle生成渐变
context.fillStyle = gr;
context.fillRect(0, 0, 200, 200);
}
如同线性渐变一样,复杂形状同样可以进行径向渐变填充。例2-23对本章前面的弧形示例应用了径向渐变,结果如图2-32显示。
例2-23 圆形径向渐变
function drawScreen(){
var gr = context.createRadialGradient(50,50,25,100,100,100);
//添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
//应用fillStyle生成渐变
context.fillStyle = gr;
context.arc(100, 100, 100, (Math.PI/180)*0, (Math.PI/180)*360, false);
context.fill();
}
例2-23将例2-22的径向渐变应用到圆上,而不是应用到矩形。这样就清除了形状背景的红色正方形。
也可以将径向渐变应用到弧形描边,就像填充那样,如例2-24和图2-23所示。
例2-24 弧形描边渐变
function drawScreen(){
var gr = context.createRadialGradient(50,50,25,100,100,100);
//添加颜色断点
gr.addColorStop(0,'rgb(255,0,0)');
gr.addColorStop(.5,'rgb(0,255,0)');
gr.addColorStop(1,'rgb(255,0,0)');
//应用fillStyle生成渐变
context.strokeStyle = gr;
context.arc(100, 100, 50, (Math.PI/180)*0, (Math.PI/180)*360, false)
context.stroke();
}
https://yqfile.alicdn.com/cd2f34701e5e32ef962a7c61f31a738b925e10ec.png" >
例2-24创建了一个比例2-23中小一点的圆,那么径向渐变将显示在弧形的边框上。如果与例2-23中的大小相同,这里将得到一个纯红色填充,因为径向渐变在圆形直径边缘上将是纯红色。