前言
原文链接:http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html
是html5出现的新标签,像所有dom对象一样它有本身的属性、方法和事件,其中就有绘图的方法,js能够调用它来进行绘图。
基本知识
context:是一个封装了很多绘图功能的对象,获取这个对象的方法是
var context=ducument.getElementById("2d");
canvas元素绘制图像的时候有两种方法,分别是
context.fill()//填充
context.stroke()//绘制边框
style:在进行图形绘制前,需要设置好绘图的样式
context.fillStyle//填充样式
context.strokeStyle//边框样式
context.lineWidth//图形边框宽度
颜色的表示方式:
- 直接用颜色名称:”red”,”green”,”blue”
- 十六进制颜色值:“#FFFFEE”
- rgb(1-255,1-255,1-255)
- rgba(1-255,1-255,1-255,透明度) //透明度在0到1之间,
绘制矩形
context.fillRect(x,y,width,height) strokeRect(x,y,width,height)
x:表示矩形起点横坐标
y:表示矩形起点纵坐标
width:矩形的长度
height:矩形的高度
window.onload=function(){
var canvas=document.getElementById("can");
if(canvas==null){
return false;
}
var context=canvas.getContext("2d");
//绘制矩形
context.fillRect(0,0,100,100);
context.strokeRect(120,0,100,100)
//设置纯色
context.fillStyle = "red";
context.strokeStyle = "blue";
context.fillRect(240, 0, 100, 100);
context.strokeRect(0, 120, 100, 100);
//设置透明度实践证明透明度值
context.fillStyle = "rgba(255,0,0,0.2)";
context.strokeStyle = "rgba(255,0,0,0.2)";
context.fillRect(120,120 , 100, 100);
context.strokeRect(240, 120, 100, 100);
}
清除矩形区域
context.clearRect(x,y,width,height)
x:清除矩形起点横坐标
y:清除矩形起点纵坐标
width:清除矩形长度
height:清除起点高度
context.clearRect(0,0,200,200);
圆弧
context.arc(x,y,radius,starAngle,endAngle,anticlockwise)
x:圆心的x坐标
y:圆心的y坐标
radius:圆弧半径
starAngle:开始角度
endAngle:结束角度
anticlockwise:是否逆时针(true为逆时针,false为顺时针)
//绘制圆弧
context.beginPath();
context.arc(100,100,100,0,2*Math.PI);
context.closePath();
context.fillStyle = "rgba(0,255,0,0.25)";
context.fill();
路径
context.beginPath() context.closePath()
//路径
//左侧1/4圆弧
context.beginPath();
context.arc(100,150,50,0,Math.PI/2,false);
context.fillStyle="rgba(255,0,0,0.25)";
context.fill();
context.strokeStyle="rgba(255,0,0,0.25)";
context.closePath();
context.stroke();
//右侧1/4圆弧
context.beginPath();
context.arc(300,150,50,0,Math.PI/2,false);
context.fillStyle="rgba(255,0,0,0.25)";
context.fill();
context.strokeStyle="rgba(255,0,0,0.25)";
context.closePath();
context.stroke();
实验结果如下:
得出的结论有:*为重点
- 系统默认在绘制第一个路径的开始点为beginPath
*如果画完前面的路径没有重新制定beginPath,那么画其他路径的时候会将前面最近指定的beginPath后的全部路径重新绘制
每次调用context.fill()的时候会自动把当次绘制的路径的开始点和结束点相连,接着填充封闭的部分
绘制线段
context.moveTo(x,y) context.lineTo(x,y)
x:x坐标
y:y坐标
每次画线都从moveTo的点到lineTo的点
如果没有moveTo那么第一个lineTo的效果和moveTo一样
每次lineTo后如果没哟moveTo,那么下次lineTo的开始点为前一次lineTo的结束点
//绘制线段
context.strokeStyle="rgb(250,0,0)";
context.fillStyle="rgb(250,0,0)";
context.lineTo(150,115);
context.lineTo(135,140);
context.lineTo(100,140);
context.lineTo(130, 160);
context.lineTo(115,190);
context.lineTo(150,170);
context.lineTo(185,190);
context.lineTo(170,160);
context.lineTo(200,140);
context.lineTo(165,140);
context.lineTo(150,115);
context.fill();
线性渐变
var lg=context.createLinearGradient(xStart,yStart,xEnd,yEnd)
线性渐变颜色 lg.addColorStop(offset,color);
xstart:渐变开始点x坐标
ystart:渐变开始点y坐标
xend:渐变结束点x坐标
yend:渐变结束点y坐标
offset:设定的颜色离渐变结束点的偏移量
color:绘制时要使用的颜色
//线性渐变
var g1 = context.createLinearGradient(0, 0, 0, 300);
g1.addColorStop(0, 'rgb(255,0,0)'); //红
g1.addColorStop(0.5, 'rgb(0,255,0)');//绿
g1.addColorStop(1, 'rgb(0,0,255)'); //蓝
context.fillStyle=g1;
context.fillRect(0,0,400,300);
径向渐变
var rg=context.createRadialGraient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd);
径向渐变颜色:rg.addColorStop(offset,color)
xstart:发散开始圆心x坐标
ystart:发散开始圆心y坐标
radiusstart:发散开始圆半径
xend:发散结束圆心x坐标
yend:发散结束圆心y坐标
radiusend:发散结束圆半径
offset:设定的颜色离渐变结束点的偏移量(0~1)
color:绘制时要使用的颜色
//画一个同心圆球
var gl=context.createRadialGradient(200,150,0,200,150,200);
gl.addColorStop(0.1,'rgb(255,0,0)');
gl.addColorStop(1,'rgb(50,0,0)');
context.fillStyle=gl;
context.beginPath();
context.arc(200,150,100,0,Math.PI*2,true);
context.fill();
var g1=context.createRadialGradient(100,150,10,300,150,50);
g1.addColorStop(0.1,'rgb(255,0,0)');
g1.addColorStop(0.5,'rgb(0,255,0)');
g1.addColorStop(1,'rgb(0,0,255)');
context.fillStyle=g1;
context.fillRect(0,0,400,300);
图像变形
1.平移context.translate(x,y)
x:坐标原点向x轴方向平移x
y:坐标原点向y轴方向平移y
2.缩放context.scale(x,y)
x:x坐标轴按x比例缩放
y:y坐标按y比例缩放
3.旋转context,rotate(angle)
angle:坐标轴旋转x角度
//图形变形
context.save();
context.fillStyle="#eeeeff";
context.fillRect(0,0,400,300);
context.fillStyle="rgb(255,0,0,0.1)";
//平移 缩放 旋转 1 2 3
context.translate(100, 100);
context.scale(0.5, 0.5);
context.rotate(Math.PI / 4);
context.fillRect(0, 0, 100, 100);
context.restore(); //恢复到刚刚保存的状态,保存恢复只能使用一次
context.save(); //保存了当前context的状态
context.fillStyle = "rgba(255,0,0,0.2)";
//平移 旋转 缩放 1 3 2
context.translate(100, 100);
context.rotate(Math.PI / 4);
context.scale(0.5, 0.5);
context.fillRect(0, 0, 100, 100);
context.restore(); //恢复到刚刚保存的状态
context.save(); //保存了当前context的状态
context.fillStyle = "rgba(255,0,0,0.3)";
//缩放 平移 旋转 2 1 3
context.scale(0.5, 0.5);
context.translate(100, 100);
context.rotate(Math.PI / 4);
context.fillRect(0, 0, 100, 100);
context.restore(); //恢复到刚刚保存的状态
context.save(); //保存了当前context的状态
context.fillStyle = "rgba(255,0,0,0.4)";
//缩放 旋转 平移 2 3 1
context.scale(0.5, 0.5);
context.rotate(Math.PI / 4);
context.translate(100, 100);
context.fillRect(0, 0, 100, 100);
context.restore(); //恢复到刚刚保存的状态
context.save(); //保存了当前context的状态
context.fillStyle = "rgba(255,0,0,0.5)";
//旋转 平移 缩放 3 1 2
context.rotate(Math.PI / 4);
context.translate(100, 100);
context.scale(0.5, 0.5);
context.fillRect(0, 0, 100, 100);
context.restore(); //恢复到刚刚保存的状态
context.save(); //保存了当前context的状态
context.fillStyle = "rgba(255,0,0,1)";
//旋转 缩放 平移 3 2 1
context.rotate(Math.PI / 4);
context.scale(0.5, 0.5);
context.translate(100, 100);
context.fillRect(0, 0, 100, 100);
由于(平移,缩放,旋转)和(平移,旋转,缩放)一样
(缩放,选装,平移)和(旋转,缩放,平移)一样
所以实验结果只能看到“4”种情况,其实是有两种情况被覆盖了
下面给出平移,缩放,旋转先后顺序不同,坐标轴的变化图
图形组合
context.globalCompositeOperation=type
图形组合就是两个图形相互叠加了图形的表现形式,是后画的覆盖掉先画的呢,还是相互重叠的部分不显示等等,至于怎么显示就取决于type的值了
type:
source-over(默认值):在原有图形上绘制新图形
destination-over:在原有图形下绘制新图形
source-in:显示原有图形和新图形的交集,新图形在上,所以颜色为新图形的颜色
destination-in:显示原有图形和新图形的交集,原有图形在上,所以颜色为原有图形的颜色
source-out:只显示新图形非交集部分
destination-out:只显示原有图形非交集部分
source-atop:显示原有图形和交集部分,新图形在上,所以交集部分的颜色为新图形的颜色
destination-atop:显示新图形和交集部分,新图形在下,所以交集部分的颜色为原有图形的颜色
lighter:原有图形和新图形都显示,交集部分做颜色叠加
xor:重叠飞部分不现实
copy:只显示新图形
绘制图形阴影
context.shadowOffsetX :阴影的横向位移量(默认值为0)
context.shadowOffsetY :阴影的纵向位移量(默认值为0)
context.shadowColor :阴影的颜色
context.shadowBlur :阴影的模糊范围(值越大越模糊)
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowColor = 'rgba(100,100,100,0.5)';
context.shadowBlur = 1.5;
context.fillStyle = 'rgba(255,0,0,0.5)';
context.fillRect(100, 100, 200, 100);
function create5Star(context) {
var n = 0;
var dx = 100;
var dy = 0;
var s = 50;
//创建路径
context.beginPath();
context.fillStyle = 'rgba(255,0,0,0.5)';
var x = Math.sin(0);
var y = Math.cos(0);
var dig = Math.PI / 5 * 4;
for (var i = 0; i < 5; i++) {
var x = Math.sin(i * dig);
var y = Math.cos(i * dig);
context.lineTo(dx + x * s, dy + y * s);
}
context.closePath();
}
context.fillStyle = "#EEEEFF";
context.fillRect(0, 0, 400, 300);
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowColor = 'rgba(100,100,100,0.5)';
context.shadowBlur =5;
//图形绘制
context.translate(0, 50);
for (var i = 0; i < 3; i++) {
context.translate(50, 50);
create5Star(context);
context.fill();
}
保存和恢复状态
保存:context.save()
恢复:context.restore()
在上面的裁剪图片提过,一旦设定了裁剪区域,后来绘制的图形都只显示裁剪区域内的内容,要“取消”这个裁剪区域才能正常绘制其他图形,其实这个“取消”是利用save()方法和restore()方法来实现的。
context.save():调用该方法,会保存当前context的状态、属性(把他理解成游戏存档)
context.restore():调用该方法就能恢复到save时候context的状态、属性(游戏回档)
context.fillStyle = "red";
context.save(); //保存了当前context的状态
context.fillStyle = "black";
context.fillRect(0, 0, 100, 100);
context.restore();//恢复到刚刚保存的状态
context.fillRect(0,120,100,100);
保存文件
canvas.toDataURL(MIME)
在canvas中绘出的图片只是canvas标签而已,并非是真正的图片,是不能右键,另存为的,我们可以利用canvas.toDataURL()这个方法把canvas绘制的图形生成一幅图片,生成图片后,就能对图片进行相应的操作了。
context.fillStyle = "rgb(0,0,225)";
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "rgb(255,255,0)";
context.fillRect(10, 20, 50, 50);
//把图像保存到新的窗口
var w=window.open(canvas.toDataURL("image/jpeg"),"smallwin","width=400,height=350");