网站建设
网站备案流程
本机IIS服务器的创建
Win7下配置本机IIS服务器
建网站需要学习的内容
使用表格布局网页
定义网页头文件元素
制作弹出网页
制作网页宣传窗
Div+CSS布局网页
CSS的常见选择器
CSS设置文本样式
CSS设置背景颜色与图像
CSS设置表格样式
HTML中使用CSS的方法
CSS3新增的部分属性1
CSS3新增的部分属性2
CSS3动画与渐变
网页显示MySQL数据库中汉字的乱码问题
HTML5的新特性
HTML5的API
HTML5音视频API
HTML5表单
HTML5表单API
HTML5画布canvas
HTML5拖放API
HTML5地理位置API
HTML5离线应用API
HTML5 Workers多线程
HTML5跨源通信
HTML5 WebSocket通信
HTML5的Web存储API
HTML5本地数据库
HTML5其他一些API
Node.js功能和使用
常用Web前端工具
WebGL编程
GLSL ES语言
使用ThreeJs库3D编程
XML可扩展标记语言
Canvas称为画布,通过使用Canvas API可以解决图形绘制需求,绘图、渲染图形、创建动画和处理图像与文字,而且还能与标准的其他特性相结合,创建完整的应用程序,甚至是2D和3D Web游戏。
1.<canvas>元素:
这个元素会在网页上创建一个空白区域,然后通过API操作这个区域。这个元素只需要少量的属性,渲染元素上的所有内容都会参考这些值。示例:
<!DOCTYPE html>
在不支持Canvas API的浏览器上,<canvas>标记之间的内容会显示在界面上。
<html lang="en">
<head>
<title>Canvas API </title>
<script src="context.js"></script>
</head>
<body>
<section id="canvasbox">
<canvas id="canvas" width="500" height="300">
你使用的浏览器不支持此功能
</canvas>
</section>
</body>
<html>
在使用<canvas>元素时,第一个要调用的方法是getContext(),它会返回画布的绘图上下文。通过这个引用,就能够使用其他API。示例:
function initiate() {
上述代码中,<canvas>元素的引用保存在canvas变量中,getContext()则创建所需要的上下文。这个方法可以接受两个值,2d和3d,分别代表2维和3维环境。目前,HTML5只支持2d。
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
}
window.addEventListener("load", initiate, false);
画布绘图上下文由从上到下、从左到右的像素网格组成,其原点位于正方形的左上角。
2.在Canvas上绘图:
在<canvas>元素及其内容准备好之后,就可以开始创建和绘制实际的图形了。通常,开发者必须准备需要绘制的图形,然后再将它发到上下文中,但是有一些方法支持直接在画布上绘图。
1)绘制矩形:
一些专门的方法用于绘制矩形,它们是唯一能够生成基础形状的方法,要想绘制其他形状必须组合使用各种绘图方法和复杂路径。这些方法包括:
·fillRect(x, y, width, height):这个方法可以绘制实心矩形,x和y属性指定矩形的左上角位置,width和height声明其尺寸。
·strokeRect(x, y, width, height):这个方法可以绘制空心矩形,即只有轮廓。
·clearRect(x, y, width, height):这个方法可用于清除属性所指定区域的像素,类似于矩形擦除器。
示例:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.strokeRect(100,100,120,120);
context.fillRect(110,110,100,100);
context.clearRect(120,120,80,80);
}
window.addEventListener("load", initiate, false);
2)颜色:
canvas默认颜色为黑色,可以使用CSS语法和以下属性指定绘图颜色:
·strokeStyle:声明形状线条的颜色
·fillStyle:声明形状内部区域的颜色
·globalAlpha:可以设置画布上绘制的所有图形的透明度
示例:
function initiate() {
代码中指定的颜色值是十六进制格式,也可以使用rgb()等函数,或者使用rgba()函数指定形状的透明度,这些函数的值必须添加双引号,例如,strokeStyle="rgba(255,165,0,1)"。还有另一个属性globalAlpha可用于设置透明度级别,语法为:globalAlpha=value,其中value是0.0~1.0之间的数值,0.0表示完全不透明,1.0表示完全透明。
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.fillStyle="#000099";
context.strokeStyle="#990000";
context.strokeRect(100,100,120,120);
context.fillRect(110,110,100,100);
context.clearRect(120,120,80,80);
}
window.addEventListener("load", initiate, false);
如果使用这些方法指定颜色值,那么指定的颜色会成为后续绘图的默认颜色。
3)渐变:
Canvas支持的渐变效果包括线性渐变或射线渐变,并且支持设置颜色转折点。
·createLinearGradient(x1,y1,x2,y2):这个函数可以在画布上创建一个渐变对象
·createRadialGradient(x1,y1,r1,x2,y2,r2):这个函数使用两个圆在画布上创建一个渐变对象,这些值表示每个圆的圆心和半径
·addColorStop(position,color):这个函数可以指定渐变颜色值,position的值在0.0~1.0之间,颜色退化效果始于color指定的颜色值。
示例:
function initiate() {
上述代码创建一个从(0,0)到(10,100)的渐变对象,并且稍微向左倾斜。addColorStop()方法负责设置颜色,最后在fillStyle属性上应用渐变效果。
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
var grad=context.createLinearGradient(0,0,10,100);
grad.addColorStop(0.5, '#0000FF');
grad.addColorStop(1, '#000000');
context.fillStyle=grad;
context.fillRect(10,10,100,100);
context.fillRect(150,10,200,100);
}
window.addEventListener("load", initiate, false);
渐变位置是相对于画布而定的,而非相对于所绘制的图形。如果将代码后面的矩形移到屏幕的新位置,渐变效果就会发生变化。
放射渐变使用表达式createRadialGradient(0,0,30,0,0,300)。示例:
var grd=context.createRadialGradient(50,50,0,100,100,90);
grd.addColorStop(0,"#0f0");
grd.addColorStop(1,"#f90");
context.fillStyle=grd;
context.beginPath();
context.arc(100,100,90,0,Math.PI*2,true);
context.fill();
4)创建路径:
通常,会在后台处理图形和图像,处理完成后发送给上下文,绘制出结果。为此,Canvas API引入了几种生成路径的方法。
路径,就像是画笔移动的地图。建立路径后,发送到上下文,就可以在画布上实际地绘制出图形。路径可能包括多种笔画,如直线、弧线、矩形等,以此构成复杂的形状。
有两种方法分别用于开始和结束一个路径:
·beginPath():这个方法会开始一个新的形状描述。创建路径前必须先调用这个方法。
·closePath():这个方法会关闭路径,用直线将最后一个点与原点相连。如果想保留开放路径,或者使用fill()方法绘制路径,则不需要调用这个方法。
有三种方法可以在画布上绘制路径:
·stroke():这个方法可以将路径绘制为轮廓形状。
·fill():这个方法会将路径绘制为实心形状,路径会自动通过一条连接最后一个点与第一个点的直线实现封闭,不需要使用closePath()。
·clip():这个方法可以在上下文中设置裁剪区域。上下文初始化后画布会占据整个区域,clip()方法会将区域裁剪变成新的形状,从而创建遮罩效果。外面的内容不会绘制。
示例:
function initiate() {
上述代码并没有绘制任何内容,只是在画布上下文中开始路径,然后使用stroke()绘制路径,将来会在界面上显示形状的轮廓。
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.beginPath();
context.stroke();
}
window.addEventListener("load", initiate, false);
下述方法可用于设置路径和创建真正的形状:
·moveTo(x,y):这个方法会将笔尖移到指定位置,可以开始或继续绘制路径
·lineTo(x,y):这个方法可以绘制一条直线,连接当前笔尖位置到x和y属性声明的新位置
·rect(x,y,width,height):这个方法可以生成一个构成路径的矩形,而非直接绘制在画布上
·arc(x,y,radius,startAngle,endAngle,direction):这个方法可以在位置(x,y)上生成弧线或圆形,半径和弧度由属性指定,最后一个是布尔值,表示顺时针或逆时针方向。
·arcTo(x1,y1,x2,y2,radius):使用切线绘制弧线,使用两个目标点和一个半径,而起始点通常会使用moveTo()方法来指定。这种方法绘制圆弧借助了两条辅助线,起始点与P1点的线和P1与P2点的线,圆弧与这个两条线相切。如context.arcTo(150,60,180,130,50);
·quadraticCurveTo(cpx,cpy,x,y):这个方法会生成二次样条曲线,连接当前笔尖位置到x和y属性声明的位置。起点是当前位置,终点由x和y确定,cpx和cpy是曲线形状控制点。
·bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y):这个方法生成贝塞尔曲线,起点是当前位置,终点由x和y确定,要声明两个控制点,以确定曲线的形状。
示例:
function initiate() {
上述代码在屏幕上会显示一个未闭合的三角形。建议在开始路径之后马上设置笔尖开始的位置。
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.beginPath();
context.moveTo(100,100);
context.lineTo(200,200);
context.lineTo(100,200);
context.stroke();
}
window.addEventListener("load", initiate, false);
示例2:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.beginPath();
context.moveTo(100,100);
context.lineTo(200,200);
context.lineTo(100,200);
context.clip();
context.beginPath();
for (f=0;f<300;f=f+10) {
context.moveTo(0,f);
context.lineTo(500,f);
}
context.stroke();
}
window.addEventListener("load", initiate, false);
上述代码示例了clip()方法的作用。这个方法并没有绘制任何内容,而是创建了一个由路径形成的遮罩,所有落在遮罩外的内容都不会绘制。其中,使用for循环生成多条相隔10像素的水平线,这些线条在画布上从左到右绘制,但只有落入三角形遮罩的线条才会显示。
绘制圆和圆弧的方法示例:
context.arc(100,100,50,0,Math.PI*2,false);
这个方法使用弧度值设定起始点,所以要使用Math.PI*2表示360°。而把角度转化为弧度,可以使用公式:radians=Math.PI/180*n,其中n为角度值。
5)线型:
线条的宽度、端点等都可以根据实际需要进行调整。有4个属性:
·lineWidth:这个属性可以指定线条粗细,默认值为1
·lineCap:这个属性可以指定线条端点形状,三个值butt、round和square
·lineJoin:这个属性可以指定两条线之间的连接点形状,三个值round、bevel和miter
·miterLimit:这个属性与lineJoin一起使用,当lineJoin属性设为miter时,可以用于确定线条交接点的延伸范围。
这些属性会影响整条路径,必须先修改线条特性,再使用新属性创建新的路径。示例:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.beginPath();
context.arc(200,150,50,0,Math.PI*2,false);
context.stroke();
context.beginPath();
context.lineWidth=10;
context.lineCap="round";
context.beginPath();
context.moveTo(230,150);
context.arc(200,150,30,0,Math.PI,false);
context.stroke();
context.lineWidth=5;
context.lineJoin=”miter”;
context.beginPath();
context.moveTo(195,135);
context.lineTo(215,155);
context.lineTo(195,155);
context.stroke();
}
window.addEventListener("load", initiate, false);
线条样式strokeStyle不仅可以设置颜色,还可以设置渐变和图案模式。fillStyle可以设置填充颜色、渐变和图案模式。
6)文字:
在画布上写文字非常简单,只需要定义一些属性和调用相应的方法。配置文字的3个属性:
·font:这个属性与CSS的font属性类似,所接受的值完全相同
·textAlign:这个属性表示对齐方式,可以接受的值有start、end、left、right和center
·textBaseline:这个属性用于设置垂直对齐方式,包括top、hanging、middle、alphabetic、ideographic和bottom
还有两个方法支持在画布上绘制文字:
·strokeText(text,x,y):这个方法会在位置(x,y)绘制指定文字的轮廓。还可以加入第4个值,以声明最大尺寸,如果文字超出这个值,那么会缩小以适应显示范围。
·fillText(text,x,y):这个方法与前一个方法类似,但绘制的是实心文字。
示例:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.font="bold 24px verdana, sans-serif";
context.textAlign="start";
context.fillText("my message", 100, 100);
}
window.addEventListener("load", initiate, false);
API还提供了另一个绘制文字的方法:
·measureText():这个方法会返回指定文字的大小信息,可用于将画笔上的文字与其他形状进行组合,计算出位置与动画碰撞等信息。示例:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.font="bold 24px verdana, sans-serif";
context.textAlign="start";
context.textBaseline="bottom";
context.fillText("my message", 100, 124);
var size=context.measureText("My message");
context.strokeRect(100, 100, size.width, 24);
}
window.addEventListener("load", initiate, false);
上述代码添加了垂直对齐方式,可以帮助了解文字在画布上的确切垂直位置。使用measureText()方法和width属性就可以计算出文字的水平尺寸。在测量得到所有尺寸后,就能够在文字周围绘制一个矩形。
7)阴影:
阴影效果也是canvas API的重要组成部分。每一条路径和文字都可以创建阴影效果。API提供了4个实现阴影效果的属性:
·shadowColor:这个属性使用CSS语法声明阴影的颜色
·shadowOffsetX:这个属性接受一个数字,确定对象阴影的水平投射距离
·shadowOffsetY:这个属性接受一个数字,确定对象阴影的垂直投射距离
·shadowBlur:这个属性可以为阴影生成模糊效果
示例:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.shadowColor="rgba(0,0,0,0.5)";
context.shadowOffsetX=4;
context.shadowOffsetY=4;
context.shadowBlur=5;
context.font="bold 50px verdana, sans-serif";
context.fillText("My message", 100, 100);
}
window.addEventListener("load", initiate, false);
上述代码使用rgba()函数设置半透明的黑色阴影,偏离对象4像素,模糊值为5。也可以在文字外的另一个图形上应用阴影效果,比如在轮廓或实心形状上。
8)转换:
Canvas支持在图形与画布本身上执行复杂的操作。这些操作可以通过5个不同的转换方法实现:
·translate(x,y):这个转换方法可用于移动画布的原点。每一个画布原点都位于(0,0),即左上角,然后在画布内的各个方向上增加,负值则落在画布外。有时候,使用负值创建复杂图形很有用,translate()方法可以将原点移到另一个位置,作为绘制的新参考点。
·rotate(angle):这个转换方法可以使画布以原点为中心旋转一定的角度,使用弧度值。
·scale(x,y):这个转换方法可以增加或减小画布的单位,从而缩小或放大所绘制的内容。水平会垂直比例都可以使用x和y进行单独修改。这些值可以是负值,从而产生镜像效果,默认值是1.0。
·transform(m1,m2,m3,m4,dx,dy):画布拥有一组属性矩阵值。此方法可以在当前矩阵之上应用一组新矩阵,从而修改画布。
·setTransform(m1,m2,m3,m4,dx,dy):这个方法可以重置当前的转换,使用其属性值创建新的转换配置。
示例:平移、旋转和缩放
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.font="bold 20px verdana, sans-serif";
context.fillText("TEXT", 50, 20);
context.translate(50,70);
context.rotate(Math.PI/180*45);
context.fillText("TEXT", 0, 0);
context.rotate(-Math.PI/180*45);
context.translate(0,100);
context.scale(2,2);
context.fillText("TEXT", 0, 0);
}
window.addEventListener("load", initiate, false);
每一次转换都会累加。例如,如果使用scale()执行两次转换,那么第二次方法会基于当前状态执行缩放。对矩阵转换方法也不例外:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.transform(3,0,0,1,0,0);
context.font="bold 20px verdana, sans-serif";
context.fillText("TEXT", 20, 20);
context.transform(1,0,0,10,0,0);
context.font="bold 20px verdana, sans-serif";
context.fillText("TEXT", 100, 20);
}
window.addEventListener("load", initiate, false);
画布矩阵默认值是(1,0,0,1,0,0),上述代码的第一次转换中,将第一个值修改为3,就可以在水平方向拉伸矩阵,转换后绘制的文字在水平方向较宽;而下一次矩阵转换,将第4个值修改为4,使矩阵在垂直方向进行拉伸。矩阵转换是在前一个转换基础上进行的,所以第2组文字会同时在水平和垂直方向拉伸。如果要重置矩阵和设置全新的转换值,则可使用setTransform()方法。
9)恢复状态:
转换的积累增加了返回前一状态的难度。Canvas API提供了两种方法以保存和取回画布状态:
·save():这个方法可以保存画布状态,包括应用的转换、样式属性值和当前裁剪路径。
·restore():这个方法可以恢复上一次保存的状态。
示例:
function initiate() {
无论执行了多少次转换,在调用restore()方法时,状态都可以完全恢复到前一个状态。
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.save();
context.translate(50,70);
context.font="bold 20px verdana, sans-serif";
context.fillText("TEXT1", 0, 30);
context.restore();
context.fillText("TEXT2", 0, 30);
}
window.addEventListener("load", initiate, false);
10)globalCompositeOperation:
有一个属性globalCompositeOperation可用于确定形状定位方式及其与画布上已绘制图形的组合方式,其默认值是source-over,表示新的图形绘制在画布已绘制图形之上。这个属性还可以设置另外11个值:
·source-in:只绘制新图形中覆盖已绘制图形的部分,其余部分及已绘制图形的其余部分都变成透明的。
·source-out:只绘制新图形中不覆盖已绘制图形的部分,其余部分及已绘制图形的其余部分都变成透明的。
·source-atop:只绘制新图形中覆盖已绘制图形的部分,已绘制图形保留,但是新图形的其余部分变成透明的。
·lighter:两个图形都绘制,但是重叠部分的颜色为指定颜色。
·xor:两个部分都绘制,但是重叠部分变成透明的。
·destination-over:这是默认值的相反值,将新图形绘制在画布已绘制的图形之下。
·destination-in:保留画布现有图形中与新图形重叠的部分,其余部分(包括新图形)都变成透明的。
·destination-out:保留画布现有图形中不与新图形重叠的部分,其余部分(包括新图形)都变成透明的。
·destination-atop:只保留现有图形与新图形中重叠的部分。
·darker:两个图形都绘制,但是重叠部分的颜色取颜色的差值。
·copy:只绘制新图形,将已绘制图形变成透明的。
只有查看globalCompositeOperation属性各个值的可视化表现,才能够理解其工作方式。示例:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
context.fillStyle="#990000";
context.fillRect(100,100,300,100);
context.globalCompositeOperation="destination-atop";
context.fillStyle="#AAAAFF";
context.font="bold 80px verdana, sans-serif";
context.fillAlign="center";
context.fillBaseline="middle";
context.fillText("TEXT", 250, 110);
}
window.addEventListener("load", initiate, false);
3.处理图像:
图像处理是Canvas API中不可或缺的特性,但是只有一个原生方法支持图像处理:
1)drawImage():
这是画布中唯一支持绘制图像的方法,这个方法可以接受很多值,得到不同的结果:
·drawImage(image, x, y):在x和y指定的位置上绘制图像,第一个值是图像引用
·drawImage(image, x, y, width, height):在画布上绘制图像之前对图像执行缩放操作,将其尺寸修改为width和height指定的尺寸值
·drawImage(image, x1, y1, width1, height1, x2, y2, width2, height2):对图像进行切割,然后以定制的尺寸和位置绘制到画布上。值x1和y1设置图像所切割部分的左上角位置,width1和height1值表示图像切割的尺寸,其余的值表示切割部分绘制在画布上的位置及其尺寸,可以与原始尺寸不同。
图像,总是同一个文档中的图像引用,可以是getcanvasentById()等方法获取,或者由一般的JavaScript方法创建的图像对象,但不支持URL,也不支持从外部资源加载文件。示例:
function initiate() {
上述代码先加载图像,然后将图像绘制到画布中。因为画布只能接收已经加载的图像,所以必须通过load事件控制图像的加载。代码添加了监听器,并且声明了一个匿名函数来处理事件。
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
var img=new Image();
img.src="http://www.minkbooks.com/content/snow.jpg";
img.addEventListener("load", function() {
context.drawImage(img, 20, 20)}, false);
}
window.addEventListener("load", initiate, false);
其中匿名函数的代码可以使用另外两种形式:
context.drawImage(img,0,0,canvas.width,canvas.height)
context.drawImage(img,135,30,50,50,0,0,200,200)
上述第一段代码会把图像拉伸到整个画布,第二段代码则抽取图像从(135,50)开始尺寸为(50,50)像素的正方形区域并将这块图像的尺寸调整为(200,200)像素然后绘制到画布的(0,0)位置。
2)图像像素数据:
其实,还有一些方法可以将图像绘制到画布上,但不是操作图像,而是操作像素数据。
每一幅图像都可以由一串表示rgba值的整数表示,这些信息是一维数组,可用于生成一幅图像。Canvas API提供了3个用于操作图像数据和处理图像的方法:
getImageData(x, y, width, height):这个方法接受属性所声明尺寸的画布矩形,然后将它转换为数据。这个方法返回一个对象,将来可以使用它的属性width、height和data访问。
putImageData(imagedata, x, y):这个方法会将imagedata的数据转换为图像,然后将它绘制到画布中由x和y指定的位置。这个方法还有4个可选参数,以dx、dy、width、height确定一个矩形范围,绘制的图像仅限制在该矩形内,类似一个裁剪的区域。
createImageData(width, height):这个方法可以创建一幅空白图像,所有像素都是透明黑色。此外,还接受数据作为属性,然后返回该数据设置的尺寸。
数组中每一个值的位置都由公式(width*4*y)+(x*4)计算得到,这是像素的第一个值(红色),其他值需要加上1,绿色为(width*4*y)+(x*4)+1,蓝色为(width*4*y)+(x*4)+2,透明值为(width*4*y)+(x*4)+3。示例:
function initiate() {
上述代码创建了一个新函数用于处理加载的图像,变为底片效果。先利用target属性创建图像引用,然后使用这个引用和drawImage()方法,将图像绘制到画布的(0,0)位置。
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
var img=new Image();
img.src="snow.jpg";
img.addEventListener("load", modimage, false);
}
function modimage(e) {
img=e.target;
context.drawImage(image,0,0);
var info=context.getImageData(0,0,175,262);
var pos;
for (x=0;x<=175;x++) {
for (y=0;y<=262;y++) {
pos=(info.width*4*y)+(x*4);
info.data[pos]=255-info.data[pos];
info.data[pos+1]=255-info.data[pos+1];
info.data[pos+2]=255-info.data[pos+2];
}
}
context.putImageData(info,0,0);
}
window.addEventListener("load", initiate, false);
由于安全限制,在将外部来源的图像绘制到画布元素之后,就无法从画布元素获取图像信息。只有当文档和图像来自同一个源(URL),getImageData()方法才能正确执行。
还有另一种方法是将画布内容作为base64编码字符串返回,toDataURL(type)方法,将来可以使用这个字符串作为另一个画布的数据源、HTML元素(如<img>)的数据源,发送到服务器或保存在文件中。
<canvas>元素有两个属性<width>和<height>,两个方法getContext()和toDataURL()。
3)图案:
图案可用于改进绘图路径。图案支持在使用图像绘制的形状上添加纹理。使用createPattern()方法创建图案,然后将它作为颜色应用到路径上。语法格式:
createPattern(image, type);
其中,image是图像的引用,可以接受4个值repeat、repeat-x、repeat-y和no-repeat。示例:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
var img=new Image();
img.src="http://www.dwenzhao.cn/content/bricks.jpg";
img.addEventListener("load", modimage, false);
}
function modimage(e) {
img=e.target;
var pattern=context.createPattern(img, "repeat");
context.fillStyle=pattern;
context.fillRect(0,0,500,300);
}
window.addEventListener("load", initiate, false);
4.在Canvas上实现动画:
动画由JavaScript代码创建。实际上,需要先擦除创建动画的画布内容,然后再绘制形状,不断地重复这个过程。在形状绘制之后就无法移动,只有擦除绘图区域,然后再次绘制内容,以此实现动画效果。在游戏或需要创建动画的应用程序中,最好使用图像代替由复杂路径构成的形状,游戏一般使用PNG图像。示例:
function initiate() {
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
img.addEventListener("mousemove", animation, false);
}
function animation(e) {
context.clearRect(0,0,300,500);
var xmouse=e.clientX;
var ymouse=e.clientY;
var xcenter=220;
var ycenter=150;
var ang=Math.atan2(xmouse-xcenter,ymouse-ycenter);
var x=xcenter+Math.round(Math.sin(ang)*10);
var y=ycenter+Math.round(Math.cos(ang)*10);
context.beginPath();
context.arc(xcenter,ycenter,20,0,Math.PI*2,false);
context.moveTo(xcenter+70,150);
context.arc(xcenter+50,150,20,0,Math.PI*2,false);
context.stroke();
context.beginPath();
context.moveTo(x+10,y);
context.arc(x,y,10,0,Math.PI*2,false);
context.moveTo(x+60,y);
context.arc(x+50,y,10,0,Math.PI*2,false);
context.fill();
}
window.addEventListener("load", initiate, false);
上述代码显示了两个紧跟鼠标指针转动的眼睛。为了移动眼睛,必须在鼠标移动时更新它们的位置。为此,添加mousemove事件监听器,当事件触发时,animation()函数就会执行。
这个函数,首先清除画布内容,然后捕捉鼠标指针位置,将第一只眼睛的位置保存在变量xcenter和ycenter中。使用鼠标位置和左眼中心位置,就可以使用atan2方法计算出两点间不可见直线的角度,使用这个角度计算出瞳孔的中心位置。在得到这些值后,就可以在画布上绘制眼睛,先绘制表示眼睛的两个圆,其中第一只眼睛的开始位置是xcenter和ycenter,第二只眼睛对应的圆向右偏移50像素。然后创建动画,使用前面通过角度计算得到的位置变量x和y,两个瞳孔用fill()方法绘制黑色实心圆表示。
5.在Cancas上处理视频:
没有专门在画布元素上处理视频的方法,只能通过获取<video>元素的每一帧,然后使用drawImage()将它作为图像绘制到画布上。示例:
<!DOCTYPE html>
这个模板包括一个JavaScript文件canvasvideo.js。内容为:
<html lang="en">
<head>
<title>Video on Canvas </title>
<style>
.boxes {
display: inline-block;
margin: 10px;
padding: 5px;
border: 1px solid #999999;
}
</style>
<script src="canvasvideo.js"></script>
</head>
<body>
<section id="boxes">
<video id="media" width="483" height="272">
<source src="http://www.dwenzhao.cn/content/trailer2.mp4">
<source src="http://www.dwenzhao.cn/content/trailer2.ogg">
</video>
</section>
<section id="boxes">
<canvas id="canvas" width="483" height="272">
你使用的浏览器不支持此功能
</canvas>
</section>
</body>
<html>
function initiate() {
上述代码使用push()函数,在单击时开始和停止视频播放。另外创建了一个processFrames()函数,使用公式将视频中每一帧的所有颜色转换为灰度颜色,将彩色视频变成黑白视频。
var canvas=document.getcanvasentById('canvas'),
context=canvas.getContext('2d');
video=document.getcanvasentById('media');
video.addEventListener("click", push, false);
}
function push() {
if (!video.paused && !video.ended) {
video.pause();
window.clearInterval(loop);
} else {
video.play();
loop=setInterval(processFrames, 33);
}
}
function processFrames() {
context.drawImage(video,0,0);
var info=context.getImageData(0,0,483,272);
var pos;
var gray;
for (x=0;x<=483;x++) {
for (y=0;y<=272;y++) {
pos=(info.width*4*y)+(x*4);
gray=parseInt(info.data[pos]*0.2989+info.data[pos+1]*0.5870
+info.data[pos+2]*0.1140);
info.data[pos]=gray;
info.data[pos+1]=gray;
info.data[pos+2]=gray;
}
}
context.putImageData(info,0,0);
}
window.addEventListener("load", initiate, false);
push()函数初始化一个轮询,每隔33毫秒执行一次processFrames()函数,从<video>中提取帧,然后使用drawImage()指令绘制到画布上,然后使用getImageData()方法从画布提取数据,在两个for循环中处理该帧的所有像素。颜色转换为灰度的公式为:Rx0.2989+Gx0.5870 +Bx0.1140。最后使用putImageData()方法将帧绘制到画布上。
出于安全考虑,文档所属域与视频所属域不同,那么画布禁止在绘制内容后再提取信息。因此,需要下载视频,并将所有文件上传到同一个服务器,才能正常使用。实际应用中,不推荐采用实时处理视频的方法,在一些计算机配置和浏览器上,视频处理可能会发生延迟。