## Canvas
**二、canvas**
HTML5`<canvas>`元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成。
`<canvas> `标签只是图形容器,您必须使用脚本来绘制图形。
要使用Canvas API,首先需要新建一个`<canvas>`网页元素
```
<canvas id="canvas" width="400" height="200">
您的浏览器不支持canvas!
</canvas>
```
width 和 height 属性定义的画布的大小。
接着,我们可以通过标签选择获取到<canvas>元素:
```
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); };
}();
```
- 前言
- JavaScript简介
- 基本概念
- 语法
- 数据类型
- 运算符
- 表达式
- 语句
- 对象
- 数组
- 函数
- 引用类型(对象)
- Object对象
- Array对象
- Date对象
- RegExp对象
- 基本包装类型(Boolean、Number、String)
- 单体内置对象(Global、Math)
- console对象
- DOM
- DOM-属性和CSS
- BOM
- Event 事件
- 正则表达式
- JSON
- AJAX
- 表单和富文本编辑器
- 表单
- 富文本编辑器
- canvas
- 离线应用
- 客户端存储(Cookie、Storage、IndexedDB)
- HTML5 API
- Video/Audio
- Geolocation API
- requestAnimationFrame
- File API
- FullScreen API
- IndexedDB
- 检测设备方向
- Blob
- vibrate
- Luminosity API
- WebRTC
- Page Visibility API
- Performance API
- Web Speech
- Notification
- 面向对象的程序设计
- 概述
- this关键字
- 原型链
- 作用域
- 常用API合集
- SVG
- 错误处理机制
- JavaScript开发技巧合集
- 编程风格
- 垃圾回收机制