牛骨文教育服务平台(让学习变的简单)

Canvas

二、canvas

HTML5<canvas>元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成。
<canvas> 标签只是图形容器,您必须使用脚本来绘制图形。

要使用Canvas API,首先需要新建一个<canvas>网页元素

<canvas id="canvas" width="400" height="200">
  您的浏览器不支持canvas!
</canvas>

width 和 height 属性定义的画布的大小。
接着,我们可以通过标签选择获取到元素:

var canvas = document.getElementById("canvas");

然后,创建context对象:

if(canvas.getContext){
  var ctx = canvas.getContext("2d");
}

调用getContext()方法时,传递一个“2d”参数,会获得一个CanvasRenderingContext2D对象,使用该对象可以在画布上绘制二维图形。我们也可将CanvasRenderingContext2D简称为“上下文对象”。

2.1 canvas的绘图用法

canvas画布提供了一个用来作图的平面空间,该空间的每个点都有自己的坐标,x表示横坐标,y表示竖坐标。原点(0, 0)位于图像左上角,x轴的正向是原点向右,y轴的正向是原点向下。

(1)绘制矩形

  • rect(x,y,width,height)方法用来绘制矩形。

  • fillRect(x, y, width, height)方法用来绘制矩形,它的四个参数分别为矩形左上角顶点的x坐标、y坐标,以及矩形的宽和高。fillStyle属性用来设置矩形的填充色。

  • strokeRect(x, y, width, height)方法同样是绘制矩形,但只画线不填充,也可以说是画空心矩形。strokeStyle属性用来设置矩形的绘制色。

  • clearRect(x, y, width, height)方法用来清除某个矩形区域的内容。

(2)绘制圆形和扇形

  • arc(x, y, radius, startAngle, endAngle, anticlockwise)方法用来绘制圆形和扇形。
    arc方法的x和y参数是圆心坐标,radius是半径,startAngle和endAngle则是扇形的起始角度和终止角度(以弧度表示),anticlockwise表示做图时应该逆时针画(true)还是顺时针画(false)。
  • arcTo(x1,y1,x2,y2,r)方法在画布上创建介于两个切线之间的弧/曲线。
    参数:x1 弧的起点的 x 坐标,y1 弧的起点的 y 坐标,x2 弧的终点的 x 坐标,y2 弧的终点的 y 坐标,r 弧的半径。

(3)绘制文本

  • fillText(string, x, y) 用来绘制文本,它的三个参数分别为文本内容、起点的x坐标、y坐标。使用之前,需用font设置字体、大小、样式(写法类似与CSS的font属性)。
    strokeText(string,x,y)方法,用来添加空心字。
    // 设置字体  
    ctx.font = "Bold 20px Arial";   
    // 设置对齐方式,start、end、right、center
    ctx.textAlign = "left";  
    // 设置填充颜色  
    ctx.fillStyle = "#008600"; 
    //设置垂直对齐方式,top、hanging、middle、alphabetic、ideographic、bottom
    ctx.textBaseline = top;
    

    我们还可以计算字体宽度(px):

    var name = "aaa";
    ctx.measureText(name);
    

    measureText() 方法返回包含一个对象,该对象包含以像素计的指定字体宽度。

    ctx.measureText(name).width
    

(4)绘制路径

beginPath()方法表示开始绘制路径,moveTo(x, y)方法设置线段的起点,lineTo(x, y)方法设置线段的终点,stroke()方法用来给透明的线段着色。

ctx.beginPath(); // 开始路径绘制  
ctx.moveTo(20, 20); // 设置路径起点,坐标为(20,20)  
ctx.lineTo(200, 20); // 绘制一条到(200,20)的直线  
ctx.lineWidth = 1.0; // 设置线宽  
ctx.strokeStyle = "#CC0000"; // 设置线的颜色  
ctx.stroke(); // 进行线的着色,这时整条线才变得可见
moveTo()和lineTo()方法可以多次使用。

注意:如果使用closePath()方法,会自动绘制一条当前点到起点的直线,形成一个封闭图形。

fill()和stroke()分别填充当前绘图(路径)和绘制已定义的路径。

isPointInPath()

isPointInPath(x,y);

如果指定的点位于当前路径中,isPointInPath() 方法返回 true,否则返回 false。

clip()

clip()方法从原始画布中剪切任意形状和尺寸。
注意:一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。您也可以在使用 clip() 方法前通过使用 save() 方法对当前画布区域进行保存,并在以后的任意时间对其进行恢复(通过 restore() 方法)。

closePath()方法创建当前点回到起始点的路径。

其他样式属性:

  • lineCap 设置或返回线条的结束端点样式,可能值: butt|round|square(平直边缘|圆形线帽|正方形线帽)
  • lineJoin 设置或返回两条线相交时,所创建的拐角类型,可能值:bevel|round|miter(斜角|圆角|尖角(默认值))
  • lineWidth 设置或返回当前的线条宽度。
  • miterLimit 正数,设置或返回最大斜接长度。如果斜接长度超过 miterLimit 的值,边角会以 lineJoin 的 "bevel" 类型来显示。
  • fillStyle 设置填充色
  • strokeStyle 设置绘制线色

颜色格式:

//可直接用颜色名称
"red" "green"
//十六进制颜色
"#d9d9d9"
//rgb
rgb(0,0,0)
//rgba
rgba(0,0,0,1)

(5)设置渐变色

线性渐变

createLinearGradient方法用来设置渐变色。

var gradient = ctx.createLinearGradient(0, 0, 0, 160);    
gradient.addColorStop(0, "#BABABA");    
gradient.addColorStop(1, "#636363");

createLinearGradient()方法的参数是(x1, y1, x2, y2),其中x1和y1是起点坐标,x2和y2是终点坐标。通过不同的坐标值,可以生成从上至下、从左到右的渐变等等。
使用方法:

ctx.fillStyle = myGradient;  
ctx.fillRect(10,10,200,100);

环形渐变

createRadialGradient()方法的参数是(x0,y0,r0,x1,y1,r1),其中x0 渐变的开始圆的 x 坐标,y0 渐变的开始圆的 y 坐标,r0 开始圆的半径,x1 渐变的结束圆的 x 坐标,y1 渐变的结束圆的 y 坐标,r1 结束圆的半径。

var grd=ctx.createRadialGradient(75,50,5,90,60,100);  
grd.addColorStop(0,"red");  
grd.addColorStop(1,"white");   
  
ctx.fillStyle=grd;  
ctx.fillRect(10,10,150,100);

(6)设置阴影

我们还可以设置阴影

ctx.shadowOffsetX = 10; // 设置水平位移  
ctx.shadowOffsetY = 10; // 设置垂直位移  
ctx.shadowBlur = 5; // 设置模糊度  
ctx.shadowColor = "rgba(0,0,0,0.5)"; // 设置阴影颜色   

ctx.fillStyle = "#CC0000";   
ctx.fillRect(10,10,200,100);

(7)合成

globalAlpha 属性设置或返回绘图的当前透明值(alpha 或 transparency)。
globalAlpha 属性值必须是介于 0.0(完全透明) 与 1.0(不透明) 之间的数字。
ctx.globalAlpha = number

globalCompositeOperation属性设置或返回如何将一个源(新的)图像绘制到目标(已有的)的图像上。
源图像 = 您打算放置到画布上的绘图。
目标图像 = 您已经放置在画布上的绘图。

source-over	默认。在目标图像上显示源图像。  
source-atop	在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。  
source-in	在目标图像中显示源图像。只有目标图像之内的源图像部分会显示,目标图像是透明的。  
source-out	在目标图像之外显示源图像。只有目标图像之外的源图像部分会显示,目标图像是透明的。  
destination-over	在源图像上显示目标图像。  
destination-atop	在源图像顶部显示目标图像。目标图像位于源图像之外的部分是不可见的。  
destination-in	在源图像中显示目标图像。只有源图像之内的目标图像部分会被显示,源图像是透明的。  
destination-out	在源图像之外显示目标图像。只有源图像之外的目标图像部分会被显示,源图像是透明的。  
lighter	显示源图像 + 目标图像。  
copy	显示源图像。忽略目标图像。  
xor	使用异或操作对源图像与目标图像进行组合。

2.2 绘制图像

Canvas API 允许将图像文件插入画布。

我们可以使用Image对象来加载图片,然后绘制:

var image = new Image();
image.onload = function(){
    ctx.drawImage(image,0,0);
};
image.src="new.jpg";

drawImage方法

drawImage(img,x,y)
drawImage(img,x,y,width,height)
drawImage(img,sx,sy,switch,sheight,x,y,width,height)

参数:
img 规定要使用的图像、画布或视频;sx 可选,开始剪切的 x 坐标位置;sy 可选,开始剪切的 y 坐标位置;swidth 可选,被剪切图像的宽度;sheight 可选,被剪切图像的高度;x 表示在画布上放置图像的 x 坐标位置;y 在画布上放置图像的 y 坐标位置;width 可选,表示要使用的图像的宽度(伸展或缩小图像);height 可选,表示要使用的图像的高度(伸展或缩小图像)。

图像平铺

createPattern(image,type)

参数:
type: no-repeat:不平铺 ;repeat-x:横方向平铺;repeat-y:纵方向平铺;repeat:全方向平铺

2.3 像素处理

通过getImageData方法和putImageData方法,可以处理每个像素,进而操作图像内容。

getImageData()方法可以用来读取Canvas的内容,返回一个对象,包含了每个像素的信息。

var imageData = ctx.getImageData(x,y,w,h)

参数:x是canvas的X轴坐标,y是canvas的Y轴坐标,w是宽度,h是高度。
getImageData()方法返回一个像素颜色数组(该数组的长度等于图像的像素宽度图像的像素高度4,每个值的范围是0-255,可读写),imageData的属性data就是指向它,顺序是所取像素范围的从左到右,从上到下,数组的元素是(所有图形,包括图片,和绘制的图形)每个像素的rgba :

[r1,g1,b1,a1,r2,g2,b2,a2...]

putImageData()方法可将数组内容重新绘制到Canvas上。

putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);

参数:imgData 规定要放回画布的 ImageData 对象;x 是ImageData 对象左上角的 x 坐标,以像素计;y 是ImageData 对象左上角的 y 坐标,以像素计;dirtyX 可选,水平值(x),以像素计,在画布上放置图像的位置;dirtyY 可选,垂直值(y),以像素计,在画布上放置图像的位置;dirtyWidth 可选,在画布上绘制图像所使用的宽度;dirtyHeight 可选,在画布上绘制图像所使用的高度。

当然,我们也可以创建一个空白的ImageData对象。

var imgData=context.createImageData(width,height);

也可创建与指定的另一个ImageData对象尺寸相同的新ImageData对象(其不会复制图像数据):

var imgData=context.createImageData(imageData);

ImageData对象有data属性,它包含 color/alpha 信息的数组。

2.4 保存与恢复

save()方法用于保存上下文环境,restore()方法用于恢复到上一次保存的上下文环境。

2.5 保存图像

我们可以使用toDataURL()方法将Canvas数据重新转化成图像文件形式:

canvas.toDataURL("image/png")

上面的代码将Canvas数据,转化成PNG data URI。

2.6 转换

(1)scale()

scale() 方法缩放当前绘图至更大或更小。

scale(scalewidth,scaleheight)

参数:scalewidth 缩放当前绘图的宽度;scaleheight 缩放当前绘图的高度。

注意:如果您对绘图进行缩放,所有之后的绘图也会被缩放。定位也会被缩放。如果您 scale(2,2),那么绘图将定位于距离画布左上角两倍远的位置。

(2)rotate()

rotate() 方法旋转当前的绘图。

rotate(angle)

参数:angle 旋转角度,以弧度计。
注意:旋转只会影响到旋转完成后的绘图。

(3)translate()

translate() 方法重新映射画布上的 (0,0) 位置。

translate(x,y)

参数:x 添加到水平坐标(x)上的值;y 添加到垂直坐标(y)上的值。

(4)transform()

transform(a,b,c,d,e,f)

参数:a 水平缩放绘图,b 水平倾斜绘图,c 垂直倾斜绘图,d 垂直缩放绘图,e 水平移动绘图,f 垂直移动绘图。

(5)setTransform()

setTransform() 方法把当前的变换矩阵重置为单位矩阵,然后以相同的参数运行 transform()。

setTransform(a,b,c,d,e,f)

参数:a 水平缩放绘图,b 水平倾斜绘图,c 垂直倾斜绘图,d 垂直缩放绘图,e 水平移动绘图,f 垂直移动绘图。
注意:该变换只会影响 setTransform() 方法调用之后的绘图。

2.7 动画

我们可以使用setInterval()setTimeout()来产生动画效果。

还可以使用requestAnimationFrame()来制作动画。
requestAnimationFrame()函数是全局函数。

考虑兼容,如下:

var requestAnimFrame = function() {   
  return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(a) {window.setTimeout(a, 1e3 / 60, (new Date).getTime())};   
}();

使用方法:

function step(){
  requestAnimationFrame(step);
}

requestAnimationFrame()方法会返回一个requestID,是一个长整型非零值,作为一个唯一的标识符,可将该值作为参数传递给window.cancelAnimationFrame()来取消这个函数。

cancelAnimationFrame(requestID);

兼容性代码:

var cancelAnimFrame = function() {   
  return window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || function(id) { clearTimeout(id); }; 
}();