var canvas = document.getElementById('trails');
var context = canvas.getContext('2d');
// 画布的状态
context.save(); 该方法在画之前在栈中保存绘画一个副本,用于后面进行绘画。
context.restore(); 保存并结束当前绘画,弹出栈恢复成初始状态,该方法前必须先调save()方法。
// 矩阵变换
1.放缩变换:context.scale(x,y); 该方法两个参数,进行水平,垂直间比例缩放。
2.旋转变换:context.rotate(angel); 该方法一个参数,按顺时针旋转angel度。
3.平移变换:context.translate(x,y); 该方法的两个参数,进行水平,垂直间整体平移
4.多样变换:context.transform(m11,m12,m21,m22,dx,dy); 该方法四个参数,用于计算图像,达到变形的目的,dx按水平平移,dy按垂直平移。
a.可以用transform(1,0,0,1,x,y)或者transform(0,1,1,0,x,y)替换translate(x,y)
b.可以用transform(x,0,0,t,0,0)或者transform(0,y,x,0,0,0)替换scale(x,y)
c.可以用transform(Math.cos(angle*Math.PI/180), Math.sin(angle*Math.PI/180), -Math.sin(angle*Math.PI/180),Math.cos(angle*Math.PI/180)),0,0)
或者transform(-Math.sin(angle*Math.PI/180), Math.cos(angle*Math.PI/180), Math.cos(angle*Math.PI/180), Math.sin(angle*Math.PI/180)),0,0) 替换rotate(angle)
eg.绘制彩虹
function draw(id)
{
var canvas=document.getElementById(id);
if(canvas==null)
return false;
var context=canvas.getContext('2d');
//定义颜色
var colors=["red","orange","yellow","green","blue","navy","purple"];
//定义线宽
context.lineWidth=10;
context.transform(1,0,0,1,100,0);
//循环绘制圆弧
for(var i=0;i<7;i++){
context.transform(1,0,0,1,0,10);
context.strokeStyle=colors[i];
context.beginPath();
context.arc(50,100,100,0,Math.PI,true);
context.stroke();
}
}
//混合图像
context.globalAlpha[ = value]; 适用于形状与图形合成前的操作,改变其alpha值(0.0-1.0).
context.globalCompositeOperation [=type]; 实现现有图形的组合。其中type有如下取直:
a.source-atop:表示值绘制新图形中与原有图形重叠的部分与未被重叠覆盖的原有图形,新图形的其他部分变成透明
b.source-in:表示新图形与原有图形做in运算,只显示新图形中与原有图形相重叠的部分,新图形与原有图形的其他部分均变成透明
c.source-out:表示新图形与原有图形做out运算,只显示新图形中与原有图形不重叠的部分,新图形与原有图形的其他部分均变成透明
d.source-over (default):表示新图形覆盖在原有图形之上
e.destination-atop:表示只绘制原有图形中被新图形重叠覆盖的部分与新图形的其他部分,原有图形中的其他部分变成透明,不绘制新图形中与原有图形相重叠的部分
f.destination-in:表示原有图形与新图形做in运算,只显示原有图形中与新图形相重叠的部分,新图形与原有图形的其他部分均变成透明
g.destination-out:表示原有图形与新图形做out运算,只显示原有图形中与新图形不重叠的部分,新图形与原有图形的其他部分均变成透明
h.destination-over:表示在原有图形之下绘制新图形
i.lighter:表示原有图形与新图形均绘制,重叠部分加色处理
j.copy:表示只绘制新图形,原有图形中未与新图形重叠的部分变成透明
k.xor:表示值绘制新图形中与原有图形不重叠的部分,重叠部分变成透明
a. b. c. d. e. f. g. h. i. j. k.
function draw(id)
{
var canvas=document.getElementById(id);
if(canvas==null)
return false;
var context=canvas.getContext('2d');
var oprtns=new Array(
"source-atop",
"source-in",
"source-out",
"source-over",
"destination-atop",
"destination-in",
"destination-out",
"destination-over",
"lighter",
"copy",
"xor"
);
var i=10;
context.fillStyle="blue";
context.fillRect(10,10,60,60);
context.globalCompositeOperation=oprtns[i];
context.beginPath();
context.fillStyle="red";
context.arc(60,60,30,0,Math.PI*2,false);
context.fill();
}
// 颜色和样式
context.strokStyle [=value]; 该方法设置图形外围形状的线条颜色或样式。
context.fillStyle [=value]; 该方法设置图形内部用颜色或样式来填充。
其中value如果不是简单的颜色值也可以设置为对象:CanvasGradient,CanvasPattern通过这两个构建出相关复杂的样式
CanvasGradient:渐变值的是指有一种颜色向另外一种颜色渐变化的填充,在相交的地方融合,呈现出梯度的变化效果 有两种渐变方式:
1.线性渐变[context.createLinearGradient(x0,y0,x1,y1)四个参数开始于x0,y0 结束于x1,y1]
2.径向渐变[context.createRadialGradient(x0,y0,r0,x1,y1,r1)六个参数开始于x0,y0并且以r0为半径,结束于x1,y1并且以r1为半径]
一旦创建了一个渐变就需要通过gradient.addColorStop(offset,color)来中止偏移量(取值为:0.0-1.0)为offset的color颜色的渐变。其中偏移量offset从开始端到结束端
< !doctype>
< html>
< head>
< title>Gradient Example< /title>
< script>
window.onload = function() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
//在一个矩形中尝试做渐变
// 创建一个线性渐变
var fillColor = context.createLinearGradient(50,50, 150,50);
// 设置渐变的颜色
fillColor.addColorStop(0.15,"red");
fillColor.addColorStop(0.35,"black");
fillColor.addColorStop(0.65,"green");
fillColor.addColorStop(0.87,"yellow");
// 把渐变对象赋值给fillstyle
context.fillStyle= fillColor;
// 绘制矩形
context.fillRect(50,50,100,100);
// 使用文本
var fillColorText = context.createLinearGradient(300,50,600,50);
fillColorText.addColorStop(0.2,"red");
fillColorText.addColorStop(0.4,"black");
fillColorText.addColorStop(0.6,"green");
fillColorText.addColorStop(0.8,"yellow");
context.fillStyle= fillColorText;
context.font="40px verdana";
context.textBaseline="top";
context.fillText("With text too!", 300,50)
// 对角线上的渐变
var fillColordiagonal = context.createLinearGradient(50,200, 100,450);
// 渐变颜色
fillColordiagonal.addColorStop(0.2,"red");
fillColordiagonal.addColorStop(0.4,"black");
fillColordiagonal.addColorStop(0.6,"green");
fillColordiagonal.addColorStop(0.75,"yellow");
// 把渐变对象赋值给fillstyle
context.fillStyle= fillColordiagonal;
// 绘制矩形
context.fillRect(50,225, 100,250);
// 绘制径向渐变
fillColorRadial = context.createRadialGradient(450,300,0, 450,300,200);
fillColorRadial.addColorStop(0, "red");
fillColorRadial.addColorStop(0.2, "black");
fillColorRadial.addColorStop(0.4, "green");
fillColorRadial.addColorStop(0.7, "yellow");
context.fillStyle = fillColorRadial;
context.rect(300,200,500,400);
context.fill();
}
< /script>
< /head>
< body>
< div>
< p>< canvas id="myCanvas" width="600" height="400">< /canvas>< /p>
< /div>
< /body>
< /html>
CanvasPattern:填充模式,采用图形填充pattern = context.createPattern(image,repetition)
参数:image 可以是image,canvas,video元素
参数:repetition有四个值:repeat(两个方向同时)repeat-x9(水平方向)repeat-y(垂直方向)no-repeat(不平铺)
// Replace the bark image with a trail gravel image
var gravel = new Image();
gravel.src = "gravel.jpg";
gravel.onload = function() {
drawTrails();
}
// Replace the solid stroke with a repeatedd background pattern
// the repeat value: repeat repeat-x repeat-y no-repeat
context.strokeStyle = context.createPattern(gravel, 'repeat');
// 线性 样式
context.lineWidth [=value]; 设置线条的宽度
context.lineCap [=value]; 设置线条端点的样式取直:butt(默认值),round(圆弧),square(方形)
context.lineJoin [=value]; 线条相交的样式:bevel(斜切面),round(圆弧),miter(斜接-默认值)
context.miterLimit [=value];当设置miter时的选项
// 阴影(所有的绘图操作都会被全局的阴影属性影响)
context.shadowColor [=value]; 设置当前阴影填充的颜色
context.shadowOffsetX =[value]; 设置阴影在水平方向的偏移量
context.shadowOffsetY = [value];设置阴影在垂直方向的偏移量
context.shadowBlur = [value]; 设置阴影的模糊程度
// 简单形状之矩形(三种简单的方法绘制矩形)
context.clearRect(x,y,with,height); 清除制定矩形区域的内容并设置为透明的
context.fillRect(x,y,with,height); 填充出一个矩形
context.strokeRect(x,y,with,height); 描边出一个矩形
context.rect();直接画矩形,端调用该方法时,moveTo方法会直接定位到(0,0)位置。
// 绘制复杂形状之路径(上下文中一直存在一个端前路径的对象,一个路径又可以一个或多个子路径,一个路径包含一个或多个点而连接成直线或曲线)
context.beginPath(); 重置端前path做预备阶段
context.moveTo(x,y); 将起始位置定位到给定坐标
context.closePath(); 标记当前路径已经关闭结束,在后面你可以在此开始新的路径
context.lineTo(x,y); 通过给定的坐标值,用直线连接到先前的一个点上
context.quadraticCurveTo(cpx,cpy,endx,endy); 绘制二次贝塞尔曲线。cpx:控制点x值,cpy:控制点y值,endx:结束点x,endy:结束点y。moveTo方法设定了起始值,控制点起到一个引力的作用
通过创建两个虚连接上下文点和结束点的切线控制点定义您的二次曲线的曲率。moveTo()方法中定义的上下文点 。控制点较远,从上下文点和结束点,将创造更清晰的曲线,移动控制点接近上下文点和结束点,将创造更广阔的曲线。参考例子:树的分形 播放卡套装 振荡气
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,endx,endy);绘制贝济埃曲线 ,采用两个控制点。
看如下图例子
function draw(id)
{
var canvas=document.getElementById(id);
if(canvas==null)
return false;
var context=canvas.getContext('2d');
context.fillStyle="#eeeeff";
context.fillRect(0,0,400,300);
var n=0;
var dx=150;
var dy=150;
var s=100;
context.beginPath();
context.globalCompositeOperation='and';
context.fillStyle='rgb(100,255,100)';
context.strokeStyle='rgb(0,0,100)';
var x=Math.sin(0);
var y=Math.cos(0);
var dig=Math.PI/15*11;
for(var i=0;i<30;i++)
{
var x=Math.sin(i*dig);
var y=Math.cos(i*dig);
context.bezierCurveTo(dx+x*s,dy+y*s-100,dx+x*s+100,dy+y*s,dx+x*s,dy+y*s);
}
context.closePath();
context.fill();
context.stroke();
}
context.arcTo(x1,y1,x2,y2,radius);
这个方法是画一个与两条射线相切的的圆弧,两条射线其中一条为穿过 Context 绘制起点,终点为 (x1, y1),另外一条为穿过 (x2, y2),终点为 (x1, y1),这条圆弧为最小的与这两条射线相切的圆弧。在调用完 arcTo 方法后,将 圆弧与 射线 (x1, y1)-(x2, y2) 的切点添加到当前路径中,做为下次绘制的起点。
context.arc(x,y,radius,startAngle,endAngel[,anticlockwise]);
arc(定义一个中心点,半径,起始角度,结束角度,和绘图方向:顺时针或逆时针)
方法用来绘制一段圆弧路径,通过圆心位置、起始弧度、终止弧度来指定圆弧的位置和大小,这个方法也不依赖于 Context 维护的绘制起点。而在画圆弧时的旋转方向则由最后一个参数 anticlockwise 来指定,如果为 true 就是逆时针,false 则为顺时针。
context.rect(x,y,with,height);该方法用于直接画矩形,当调用该方法时moveTo方法会直接定位到(0,0).
context.fill(); 填充区域形状,当调用了fillStyle填充了样式必须调用该方法关闭画出形状。否则会出现意外。
context.stroke(); 勾画出图形的轮廓,图形的边界
context.clip(); 对图形进行裁剪
context.isPointInPath(x,y);
通过路径来绘制图形,用每一个图形是一个路径,事件绑定在canvas标签上,获得事件的发生的x,y坐标。再通过 isPointInPath(),来判断点(x,y)是否在路径内,需要注意的是isPointInPath()只对当前路径(currentPath)有效,并且经测试发现,只对当前路径的第一个子路径有效(subPath,一个currentPath可以有多个subPath)。
// 聚焦元素
shuoldDraw = context.drawFocusRing(element,[canDreawCustom]);
// 插入字符与选择管理
success = context.setCaretSelectionRect(element,x,y,w,h);
rate = context.caretBlinkRate(); 返回闪烁频率
contenteditable是一个枚举类型的属性,可供选择的值有 空字符串、 true、false 或 inherit(默认)。 当为空字符串时,效果和true一致。 当一个元素的contenteditable状态为ture(contenteditable属性为空字符串,或为true,或为inherit且其父元素状态为true)时,意味着该元素是可编辑的。 否则,该元素不可编辑。
// 文本
context.font [=value]; 设置字体同css中font属性
context.textAlign [=value]; 设置显示位置取值:start(default),end,left,right,center。
context.textBaseline [=value]; 设置竖直基准线对其方式,top, hanging, middle, ideographic, bottom,alphabetic(default)
context.fillText(text,x,y[,maxWidth]); 将文本通过x,y左边输出,输出的文字是实心的
context.strokeText(text,x,y[,maxWidth]);同fillText 但输出的文字是空心的
metrics = context.measureText(text);
metrics.width
HTML5 Canvascontext对象包括一个有用的方法measureText()。当提供一个文本串时,它将在TextMetrics对象的表单中基于当前的context设置(font face, size等)返回一些关于该文本的属性。现在TextMetrics对象只有一个属性:width。
的宽度属性给定了在画布上渲染时文本的确切地像素宽度。当试图将文本居中时这将非常有用。
用width居中文本
对Text Arranger应用,我们将用TextMetrics对象将用户已经输入到textBox表单控件中的文本居中到画布。首先,我们通过将消息变量(其中包含了我们要显示的文本)传递给2D context measureText()方法的来获取TextMetrics的距离,并将其存储到一个叫做metrics的变量中:
var metrics =context.measureText(message);
然后,从metrics的width属性中获得文本的像素宽度,并将其存储到一个叫做textWidth的变量中:
var textWidth =metrics.width;
接下来,我们采用画布的宽度的一半(theCanvas.width/2)来计算屏幕的中心。同样的算出文本宽度的一半(textWidth/2)。我们这样做是因为画布上的文本在没有任何对齐设计时显示为垂直左对齐的(后面将详细介绍)。因此,居中文本我们要把它向左移动自身宽度的一半。将文本的中心放到画布的绝对中心上。当我们允许用户选择文本的垂直对齐方式时,我们会在下一部分更新它。
var xPosition =(theCanvas.width/2) - (textWidth/2);
如何计算文本的高度?
如何获得文本的高度以便当文本长度超过画布宽度时将文本截断变成多行,或在屏幕上使文本居中。这就暴露了一个问题,TextMetrics对象不包含height属性。也没有提供整个文本字体尺寸的图像,因为它并没有考虑字体下方有下划线的字体图像。然而,字体尺寸可用于估算字体在屏幕上纵向居中,如果你还要考虑将文本分割成2行或多行它的帮助就不大了。这是因为,还要将间隔考虑进来,处理间隔是非常棘手的。
出于本文表达的需要,我们将创建一个yPosition变量,用于简单地将文本定位到画布一半高度的位置,而不去设法使用字体尺寸将文本定位到画布的纵向中心(译者:这里的意思是在字体纵向居中时忽略字体大小,直接将文本置于画布一半高度处)。字体的默认基准线是中间,因此这个方法对于屏幕居中效果很好。关于基准线我们将在下一节做更多的讨论:
var yPosition =(theCanvas.height/2);
// 图片操作
drawImage(image, dx, dy) drawImage(image, dx, dy, dw, dh) drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
第一个参数image可以用HTMLImageElement,HTMLCanvasElement或者HTMLVideoElement作为参数。dx和dy是image在canvas中定位的坐标值;dw和dh是image在canvas中即将绘制区域(相对dx和dy坐标的偏移量)的宽度和高度值;sx和sy是image所要绘制的起始位置,sw和sh是image所要绘制区域(相对image的sx和sy坐标的偏移量)的宽度和高度值。
context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh); sx与sy分别表示原图像的呗复制区域在画布中的起始横坐标与起始纵坐标 sw与sh表示被复制区域的宽度与高度 dx与dy表示复制后的目标图像在画布中的起始横坐标与起始纵坐标 dw与dh表示复制后的目标图像的宽度和高度 js代码如下:
function draw(id){
var canvas=document.getElementById(id);
if(canvas==null){
return false;
}
var context=canvas.getContext('2d');
context.fillStyle="#eeeeff";
context.fillRect(0,0,400,300);
image=new Image();
image.src="tyl.jpg";
image.οnlοad=function(){
drawImg(context,image);
}
}
function drawImg(context,image){
var i=0;
context.drawImage(image,0,0,100,100);
context.drawImage(image,23,5,57,80,110,0,100,100);
}
// 基于像素级别的图片处理
这篇主要来说一下像素级图片处理,我们可以通过ImageData对象在字节级的水平来处理图像数据,先看看与此相关的一些API属性及方法:
imagedata = context.createImageData(sw, sh)
根据给定的尺寸返回一个ImageData对象,该尺寸为CSS像素值(CSS Pixel),返回的对象中的像素点都是黑色透明的,即rgba(0,0,0,0)。
createImageData()方法会根据所给的参数创建一个以sw为宽,sh为高的空白ImageData对象,当该方法只有imagedata 参数时,它将返回一个与参数所指的ImageData对象一样大小的ImageData对象,并且返回的ImageData对象是被填充为透明黑色的(transparent black)。
imagedata = context.createImageData(imagedata)
返回一个跟参数所指对象大小一致的ImageData对象,返回的对象中的像素点都是黑色透明的。
imagedata = context.getImageData(sx, sy, sw, sh)
返回包含canvas指定区域图像数据的ImageData对象
getImageData(sx, sy, sw, sh)方法返回包含在canvas坐标系中由(sx, sy), (sx+sw, sy),(sx+sw, sy+sh), (sx, sy+sh)四个坐标在canvas上所围成区域的基本像素数据的ImageData对象,如果该区域超出了canvas范围,超出的部分被填充为透明黑色的(transparent black)。
如果createImageData()和getImageData()的参数值是无穷的或NaN,或者createImageData()只有一个参数值为null,方法会抛出NOT_SUPPORTED_ERR异常,如果值为0则抛出INDEX_SIZE_ERR异常。
imagedata.width
imagedata.height
返回ImageData对象数据的实际尺寸,该值为设备像素值(Device Pixel)。
imagedata.data
返回一个一维数组,该数组包含按照RGBA顺序排列的范围从0到255的数据
context.putImageData(imagedata, dx, dy [, dirtyX, dirtyY, dirtyWidth, dirtyHeight ])
将指定的ImageData对象的数据绘制到canvas上。
putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight)方法把ImageData结构的数据描绘在canvas上,如果任一参数值是无穷或NaN的,它将抛出NOT_SUPPORTED_ERR异常;如果第一个参数不是ImageData对象或为null它将抛出TYPE_MISMATCH_ERR异常;如果最后四个参数被省略,那它们将分别被赋值为0,0,imagedata的width和imagedata的height值。
备注:globalAlpha,globalCompositeOperation,还有shadow属性在调用该方法时会被忽略。
ImageData对象必须被初始化,有宽度和高度,data属性值被初始化为一个CanvasPixelArray对象用来存放图像数据,至少要返回一个有效的一像素图像数据。
CanvasPixelArray对象包含了图像数据每个像素点有序的可索引的色值数据。这些数据从上到下,从左到右(即从左上角开始)描述了各个像素点的红,绿,蓝还有alpha值,它们的取值范围从0到255,用8个比特的数据描绘一个值。因此,该CanvasPixelArray对象包含了w×h× 4字节的数据,一个CanvasPixelArray对象的length属性必须返回这个数字。因为该对象可索引的范围就是[0,w×h× 4-1]。