JS学习14(Canvas)
2016-05-19 15:22
441 查看
canvas由Apple公司推出,现在大部分浏览器支持绘制2D图形,3D图形的绘制使用WebGL的3D上下文。
要在画布上绘图需要取得绘图上下文,使用getContext()方法并传入上下文的名字。
在使用canvas元素之前首先要检测getContext()方法是否存在以确定浏览器是否支持canvas。这个是最准确的方法
使用toDataURL()可以导出canvas元素上绘制的图像,接受一个MIME类型格式。
如果绘制到画布上的图像源自不同的域,这个方法会抛出错误。
接下来所有的描边和填充都会使用这两个值直到重新设置这两个值。
fillRect()绘制并填充
strokeRect()只画个边
clearRect()清除矩形区域,本质上是吧一块变透明
参数为x,y,width,height
线条宽度由lineWidth控制
lineCap可以控制线条末端是平头,圆头,还是方头(butt、round、square)
通过lineJoin属性可以控制线条相交的方式是圆交,斜交还是斜接(round、bevel、miter)
arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x,y)为圆心绘制一条弧线,弧线半径为radius,起始角度和结束角度为startAngle,endAngle(以弧度表示)。counterclockwise为false表示按顺时针
arcTo(x1, y1, x2, y2, radius):arcTo()方法将利用当前端点、端点1(x1,y1)和端点2(x2,y2)这三个点所形成的夹角,绘制一段与夹角的两边相切并且半径为radius的圆上弧线。弧线的起点就是当前端点所在边与圆的切点,弧线的终点就是端点2(x2,y2)所在边与圆的切点,并且绘制的弧线是两个切点之间长度最短的那个圆弧。此外,如果当前端点不是弧线起点,arcTo()方法还将添加一条当前端点到弧线起点的直线线段。
bezierCurveTo(c1x, c1y, c2x, c2y, x, y):从上一点开始绘制一条曲线,到(x,y)为止,并以(c1x,c1y),(c2x,c2y)为控制点。
lineTo(x, y):从上一点开始绘制一条直线,到(x,y)
moveTo(x, y):将绘制画笔移动到(x,y),不画线
quadraticCurveTo(cx, cy, x, y):从上一点开始绘制一条二次曲线,到(x,y)为止,并以(cx,cy)为控制点
rect(x, y, width, height):从(x,y)开始绘制一个矩形,宽和高分别为width和height。这个方法绘制的矩形是路径,不是图形哦,和前面的方法并不一样。
路径创建完毕,如果你想绘制一条连接到起点的线条,可以调用closePath()。如果路径已经完成,你想使用fillStyle填充,使用fill()方法。如果想描边,使用stroke()。还可以调用clip(),这个方法在路径上创建一个剪切区域。
还有一个方法用来在路径被关闭前判断某点是否在路径上。isPointInPath()
font:文本字体,”10px Arial”
textAlign:文本对齐,有”start”“end”“left”“right”“center”。
textBaseline:文本基线,”top”“hanging”“middle”“alphabetic” “ideographic”“bottom”
有一个辅助确定文本大小的方法,measureText(),这个方法接收一个参数,即要绘制的文本,返回一个TextMetrics对象,目前只有一个width属性。
rotate(angle):围绕原点旋转图像angle弧度
scale(scaleX, scaleY):缩放,于x乘scaleX,y乘scaleY
translate(x, y):将坐标原点移动到(x,y),以后(x,y)就是00点 ‰
transform(m1_1, m1_2, m2_1, m2_2, dx, dy):直接修改矩阵
setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):先将矩阵恢复至默认状态,再调用transform()
上下文里有好多设置,提供了保存和恢复方法来方便使用:
这里使用的是栈结构,可以存多次,再一次一次取。
只传进一个img元素或另一个canvas元素和起点坐标
再传进规定的大小,可以把图像压缩到你想要的宽高。这时宽高比例和原始图像不一样的话图像会变形。
如果你只想把原始图像的一部分画到画布上,需要9个参数:
图像、源图像x、源图像y、源图像宽、源图像高、目标图像x、目标图像y、目标图像宽、目标图像高
源图像x、源图像y说明从源图像的哪里开始截取,源图像宽、源图像高说明截取多大一部分。这些值都是相对源图像来说的。
目标图像x、目标图像y说明这幅截取完成的图最终画在画布的哪里,目标图像宽、目标图像高会将截取好的图拉伸至你给的像素。
shadowColor
shadowOffsetX
shadowOffsetY
shadowBlur
线性渐变
创建线性渐变时只需传入起点和终点
起点和终点要与你要填充的元素匹配。
镜像渐变
createRadialGradient()方法,这个方法接收6个参数,起点圆的圆心和半径,终点圆的圆心和半径。
createPattern()接收一个img,video,canvas元素和一个表示如何重复的字符串”repeat”“repeat-x” “repeat-y”“no-repeat”
要注意画布上如果有来自其他域的图片,是不能获取图像元数据的,会报错。
globalAlpha是全局透明度,介于0,1之间。默认值为0,如果某些绘制是需要透明度的,将他设置为相应值,用完再设置回0。
globalCompositionOperation表示后绘制的矩形怎么和先绘制的图形结合。有下面几种值:
source-over
source-in
source-out
source-atop
destination-over
destination-in
destination-out
destination-atop
lighter
copy
这些属性的效果大家自己测试吧,不同浏览器实现有差别,真正要用的时候要注意哦。
http://www.hiwebgl.com/?p=42
基本用法
首先最重要的就是要给canvas画布一个宽高。要在画布上绘图需要取得绘图上下文,使用getContext()方法并传入上下文的名字。
在使用canvas元素之前首先要检测getContext()方法是否存在以确定浏览器是否支持canvas。这个是最准确的方法
var drawing = document.getElementById("drawing"); if (drawing.getContext){ var context = drawing.getContext("2d"); }
使用toDataURL()可以导出canvas元素上绘制的图像,接受一个MIME类型格式。
if (drawing.getContext){ var imgURI = drawing.toDataURL("image/png"); var image = document.createElement("img"); image.src = imgURI; document.body.appendChild(image); }
如果绘制到画布上的图像源自不同的域,这个方法会抛出错误。
2D上下文
2D上下文的坐标开始于左上角(0,0),所有坐标值都基于这个原点计算。填充和描边
2D上下文的两种基本绘图操作是填充和描边,而操作结果取决于两个属性:fillStyle和strokeStyle。这两个属性的值可以是字符串,渐变对象或模式对象。context.strokeStyle = "red"; context.fillStyle = "#0000ff";
接下来所有的描边和填充都会使用这两个值直到重新设置这两个值。
绘制矩形
矩形是唯一一种可以直接设置的形状,有3个方法fillRect()绘制并填充
strokeRect()只画个边
clearRect()清除矩形区域,本质上是吧一块变透明
参数为x,y,width,height
var context = drawing.getContext("2d"); context.fillStyle = "#ff0000"; context.fillRect(10, 10, 50, 50); context.fillStyle = "rgba(0,0,255,0.5)"; context.fillRect(30, 30, 50, 50); context.strokeStyle = "#ff0000"; context.strokeRect(100, 10, 50, 50); context.strokeStyle = "rgba(0,0,255,0.5)"; context.strokeRect(120, 30, 50, 50); context.clearRect(40, 40, 10, 10);
线条宽度由lineWidth控制
lineCap可以控制线条末端是平头,圆头,还是方头(butt、round、square)
通过lineJoin属性可以控制线条相交的方式是圆交,斜交还是斜接(round、bevel、miter)
绘制路径
首先调用beginPath()方法,表示要开始绘制新的路径。然后调用下面的方法来绘制实际的路径:arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x,y)为圆心绘制一条弧线,弧线半径为radius,起始角度和结束角度为startAngle,endAngle(以弧度表示)。counterclockwise为false表示按顺时针
arcTo(x1, y1, x2, y2, radius):arcTo()方法将利用当前端点、端点1(x1,y1)和端点2(x2,y2)这三个点所形成的夹角,绘制一段与夹角的两边相切并且半径为radius的圆上弧线。弧线的起点就是当前端点所在边与圆的切点,弧线的终点就是端点2(x2,y2)所在边与圆的切点,并且绘制的弧线是两个切点之间长度最短的那个圆弧。此外,如果当前端点不是弧线起点,arcTo()方法还将添加一条当前端点到弧线起点的直线线段。
bezierCurveTo(c1x, c1y, c2x, c2y, x, y):从上一点开始绘制一条曲线,到(x,y)为止,并以(c1x,c1y),(c2x,c2y)为控制点。
lineTo(x, y):从上一点开始绘制一条直线,到(x,y)
moveTo(x, y):将绘制画笔移动到(x,y),不画线
quadraticCurveTo(cx, cy, x, y):从上一点开始绘制一条二次曲线,到(x,y)为止,并以(cx,cy)为控制点
rect(x, y, width, height):从(x,y)开始绘制一个矩形,宽和高分别为width和height。这个方法绘制的矩形是路径,不是图形哦,和前面的方法并不一样。
路径创建完毕,如果你想绘制一条连接到起点的线条,可以调用closePath()。如果路径已经完成,你想使用fillStyle填充,使用fill()方法。如果想描边,使用stroke()。还可以调用clip(),这个方法在路径上创建一个剪切区域。
if (drawing.getContext){ var context = drawing.getContext("2d"); context.beginPath(); context.arc(100, 100, 99, 0, 2 * Math.PI, false); context.moveTo(194, 100); context.arc(100, 100, 94, 0, 2 * Math.PI, false); context.moveTo(100, 100); context.lineTo(100, 15); context.moveTo(100, 100); context.lineTo(35, 100); context.stroke(); }
还有一个方法用来在路径被关闭前判断某点是否在路径上。isPointInPath()
绘制文本
绘制文本主要有两个方法,fillText()和strokeText()。接收4个参数,要绘制的文本字符串,x坐标,y坐标,最大像素宽度。这两个方法以3个属性为基础:font:文本字体,”10px Arial”
textAlign:文本对齐,有”start”“end”“left”“right”“center”。
textBaseline:文本基线,”top”“hanging”“middle”“alphabetic” “ideographic”“bottom”
context.font = "bold 14px Arial"; context.textAlign = "center"; context.textBaseline = "middle"; context.fillText("12", 100, 20);
有一个辅助确定文本大小的方法,measureText(),这个方法接收一个参数,即要绘制的文本,返回一个TextMetrics对象,目前只有一个width属性。
变换
这个也是基于上下文的设置,在下次设置前不会改变。rotate(angle):围绕原点旋转图像angle弧度
scale(scaleX, scaleY):缩放,于x乘scaleX,y乘scaleY
translate(x, y):将坐标原点移动到(x,y),以后(x,y)就是00点 ‰
transform(m1_1, m1_2, m2_1, m2_2, dx, dy):直接修改矩阵
setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):先将矩阵恢复至默认状态,再调用transform()
上下文里有好多设置,提供了保存和恢复方法来方便使用:
这里使用的是栈结构,可以存多次,再一次一次取。
context.fillStyle = "#ff0000"; context.save(); context.fillStyle = "#00ff00"; context.translate(100, 100); context.rotate(1); context.save(); context.fillStyle = "#0000ff"; context.fillRect(120, 0, 100, 200); //(100,100) context.restore(); context.fillRect(10, 10, 100, 200); //(110,110) context.restore(); context.fillRect(0, 0, 100, 200);
绘制图像
可以把一幅图像绘制在画布上,有3种调用方式:只传进一个img元素或另一个canvas元素和起点坐标
context.drawImage(image, 10, 10);
再传进规定的大小,可以把图像压缩到你想要的宽高。这时宽高比例和原始图像不一样的话图像会变形。
context.drawImage(image, 50, 10, 20, 30);
如果你只想把原始图像的一部分画到画布上,需要9个参数:
图像、源图像x、源图像y、源图像宽、源图像高、目标图像x、目标图像y、目标图像宽、目标图像高
context.drawImage(image, 0, 10, 50, 50, 0, 100, 40, 60);
源图像x、源图像y说明从源图像的哪里开始截取,源图像宽、源图像高说明截取多大一部分。这些值都是相对源图像来说的。
目标图像x、目标图像y说明这幅截取完成的图最终画在画布的哪里,目标图像宽、目标图像高会将截取好的图拉伸至你给的像素。
阴影
2D上下文会依据以下几个属性的值,自动为形状或路径绘制出阴影。shadowColor
shadowOffsetX
shadowOffsetY
shadowBlur
context.shadowOffsetX = 5; context.shadowOffsetY = 5; context.shadowBlur = 4; context.shadowColor = "rgba(0, 0, 0, 0.5)";
渐变
渐变由CanvasGradient实例表示线性渐变
创建线性渐变时只需传入起点和终点
起点和终点要与你要填充的元素匹配。
var gradient = context.createLinearGradient(0, 0, 100, 200); gradient.addColorStop(0, "red"); gradient.addColorStop(0.165, "orange"); gradient.addColorStop(0.33, "yellow"); gradient.addColorStop(0.495, "green"); gradient.addColorStop(0.66, "#2aabd2"); gradient.addColorStop(0.825, "blue"); gradient.addColorStop(1, "#e4b9b9"); context.fillStyle = gradient; context.fillRect(0, 0, 100, 200);
镜像渐变
createRadialGradient()方法,这个方法接收6个参数,起点圆的圆心和半径,终点圆的圆心和半径。
var gradient2 = context.createRadialGradient(170, 250, 0, 170, 250, 50); gradient2.addColorStop(0, "red"); gradient2.addColorStop(0.165, "orange"); gradient2.addColorStop(0.33, "yellow"); gradient2.addColorStop(0.495, "green"); gradient2.addColorStop(0.66, "#2aabd2"); gradient2.addColorStop(0.825, "blue"); gradient2.addColorStop(1, "#e4b9b9"); context.fillStyle = gradient2;
模式
模式其实就是重复的图像,可以用来填充或描边图形createPattern()接收一个img,video,canvas元素和一个表示如何重复的字符串”repeat”“repeat-x” “repeat-y”“no-repeat”
pattern = context.createPattern(img, "repeat"); context.fillStyle = pattern;
使用图像数据
2D上下文的一个明显长处就是,可以通过getImageData()取得原始图像数据,传入4个参数,起点和宽高,返回的对象是一个ImageData的实例,每个实例有3个属性,width,height,data。data是个数组,保存着每个像素的数据,每个像素用4个元素:红、绿、蓝、透明度。值的范围都在0-255。这样就可以对图像的元数据进行操作了。下面的代码实现了近似的灰阶过滤,并使用putImageData()重绘了整个画布:if (drawing.getContext){ var context = drawing.getContext("2d"), imageData, data, i, len, average, red, green, blue, alpha; imageData = context.getImageData(0, 0, drawing.width, drawing.height); data = imageData.data; for (i=0, len=data.length; i < len; i+=4){ red = data[i]; green = data[i+1]; blue = data[i+2]; alpha = data[i+3]; // rgb average = Math.floor((red + green + blue) / 3); data[i] = average; data[i+1] = average; data[i+2] = average; } // imageData.data = data; context.putImageData(imageData, 0, 0); }
要注意画布上如果有来自其他域的图片,是不能获取图像元数据的,会报错。
合成
还有两个会应用到2D上下文中所有绘制操作的属性:globalAlpha和globalCompositionOperationglobalAlpha是全局透明度,介于0,1之间。默认值为0,如果某些绘制是需要透明度的,将他设置为相应值,用完再设置回0。
globalCompositionOperation表示后绘制的矩形怎么和先绘制的图形结合。有下面几种值:
source-over
source-in
source-out
source-atop
destination-over
destination-in
destination-out
destination-atop
lighter
copy
这些属性的效果大家自己测试吧,不同浏览器实现有差别,真正要用的时候要注意哦。
WebGL
这部分请参考:http://www.hiwebgl.com/?p=42
相关文章推荐
- Extjs4.0 最新最全视频教程
- Javascript中toFixed方法的改进
- 5个常见可用性错误和解决方案
- js数组实现图片轮播
- HTML5调用摄像头实例
- Canvas 在高清屏下绘制图片变模糊的解决方法
- js可突破windows弹退效果代码
- JSP脚本漏洞面面观
- 使用BAT一句话命令实现快速合并JS、CSS
- js显示当前星期的起止日期的脚本
- 爆炸式的JS圆形浮动菜单特效代码
- js select常用操作控制代码
- JS实现不使用图片仿Windows右键菜单效果代码
- 从jsp发送动态图像
- 原生js结合html5制作小飞龙的简易跳球
- js 页面模块自由拖动实例
- js实现小鱼吐泡泡在页面游动特效
- js 提交和设置表单的值
- PHP VBS JS 函数 对照表
- node.js抓取并分析网页内容有无特殊内容的js文件