1,彩色字体
(结合字体和渐变)
- fillText(text,x,y) - 绘制实心的文本
- strokeText(text,x,y) - 绘制空心的文本
- createLinearGradient(x,y,x1,y1) - 创建线条渐变
- createRadialGradient(x,y,r,x1,y1,r1) - 创建一个径向/圆渐变
-
var cxt = c.getContext("2d"); var grd = cxt.createLinearGradient(10,10,120,10); grd.addColorStop(0,"purple"); grd.addColorStop(0.25,"blue"); grd.addColorStop(0.5,"green"); grd.addColorStop(1,"red"); cxt.strokeStyle = grd; cxt.font = "60px Arial"; cxt.strokeText("smile!",10,120);
2,贝塞尔曲线
绘制贝塞尔曲线(贝济埃、bezier) context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)
cp1x:第一个控制点x坐标
cp1y:第一个控制点y坐标
cp2x:第二个控制点x坐标
cp2y:第二个控制点y坐标
x:终点x坐标
y:终点y坐标
绘制二次样条曲线 context.quadraticCurveTo(qcpx,qcpy,qx,qy)
qcpx:二次样条曲线控制点x坐标
qcpy:二次样条曲线控制点y坐标
qx:二次样条曲线终点x坐标
qy:二次样条曲线终点y坐标
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 function draw24(id) {
2 var canvas = document.getElementById(id);
3 if (canvas == null) {
4 return false;
5 }
6 var context = canvas.getContext("2d");
7
8 context.moveTo(50, 50);
9 context.bezierCurveTo(50, 50,150, 50, 150, 150);
10 context.stroke();
11 context.quadraticCurveTo(150, 250, 250, 250);
12 context.stroke();
13 }
var cxt = c.getContext("2d"); cxt.moveTo(10,10); cxt.bezierCurveTo(10,10,100,50,60,150); cxt.stroke(); cxt.quadraticCurveTo(60,170,180,200); cxt.stroke();
3,图形变形
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角度(角度变化模型和画圆的模型一样)
var cxt = c.getContext("2d"); //0,初始 cxt.fillStyle = "blue"; cxt.strokeStyle = "green"; cxt.strokeRect(0,0,50,50); //1,位移 cxt.translate(30,30); cxt.fillRect(0,0,50,50); //2,缩放 cxt.restore(); cxt.save(); cxt.fillStyle = "red"; cxt.scale(0.8,0.8); cxt.fillRect(0,0,50,50); //3,旋转 cxt.restore(); cxt.save(); cxt.fillStyle = "yellow"; cxt.translate(80,80); cxt.rotate(Math.PI/4); cxt.fillRect(0,0,50,50);
由上可见:
1,可将此看做是平移,缩放,旋转的坐标轴。
2,平移,缩放,旋转的顺序不同都将画出不同的效果。
简单平移,缩放,旋转先后顺序不同,坐标轴的变化图
4,矩阵变换 context.transform(m11,m12,m21,m22,dx,dy)
所谓的矩阵变换其实是context内实现平移,缩放,旋转的一种机制
各参数意义对应如下表:
参数 | 意义 |
---|---|
m11 | 水平缩放(1) |
m12 | 水平倾斜(0) |
m21 | 垂直倾斜(0) |
m22 | 垂直缩放(1) |
dx | 水平位移(0) |
dy | 垂直位移(0) |
调用translate()方法只是简单地将坐标原点进行上、下、左、右移动。
rotate()方法会将坐标轴根据指定角度里进行顺时针旋转。
scale()方法实现对x轴或由y轴上的距离进行延长和缩短。传递负值会实现
scale以坐标原点做参照点将坐标轴进行翻转。就好像镜子中的镜像。
translate用来将坐标原点移动到画布最左下角,然后scale方法用于实现将y轴进行翻转,这样的就变成了越往上y轴越大。
从数学角度来理解坐标系变换:
translate、rotate和scale方法想象成对坐标轴的变换,就很容易理解了。
建议使用transform()的时候,可以在如下几个情况下使用:
1.使用context.transform (1,0,0,1,dx,dy)代替context.translate(dx,dy)
2.使用context.transform(sx,0,0,sy,0,0)代替context.scale(sx, sy)
3.使用context.transform(0,b,c,0,0,0)来实现倾斜效果(最实用)。
不用再使用它去实现旋转了,另外也没有也不用全记这些结论,直接记下abcdef六个参数的意义,效果是一样的。
//0,初始 var ctx = c.getContext("2d"); ctx.strokeStyle = "red"; ctx.lineWidth = 10; //设置stroke的线宽度 ctx.strokeRect(10,10,50,50); ctx.strokeStyle = "green"; ctx.fillStyle = "yellow"; ctx.save(); //1,位移(80,0) ==》 ctx.translate(80,0); ctx.transform(1,0,0,1,80,0); ctx.fillRect(10,10,50,50); ctx.strokeRect(10,10,50,50); //2,缩放(1.2,1.2) ==》 ctx.scale(1.2,1.2)同时位移 ctx.transform(1.2,0,0,1.2,80,0); ctx.fillRect(10,10,50,50); ctx.strokeRect(10,10,50,50); //3,倾斜(0.2,0.2) 同时位移 ctx.transform(1,0.2,0.2,1,80,0); ctx.fillRect(10,10,50,50); ctx.strokeRect(10,10,50,50);
5,setTransform()方法
transform()方法的行为相对于由 rotate(),scale(), translate(), or transform() 完成的其他变换。例如:如果我们已经将绘图设置为放到两倍,则 transform() 方法会把绘图放大两倍,那么我们的绘图最终将放大四倍。这一点和之前的变换是一样的。
但是setTransform()不会相对于其他变换来发生行为。它的参数也是六个,context.setTransform(a,b,c,d,e,f),与transform()一样。
//0,初始 var ctx = c.getContext("2d"); ctx.strokeStyle = "red"; ctx.lineWidth = 10; //设置stroke的线宽度 ctx.strokeRect(10,10,80,80); ctx.fillStyle = "yellow"; ctx.save(); //1,位移(80,0) ==》 ctx.translate(80,0); ctx.transform(1,0,0,1,100,0); ctx.fillRect(10,10,80,80); //2,缩放(0.8,0.8) ==》 在0,初始的基础的上缩放 ctx.setTransform(0.8,0,0,0.8,0,0); ctx.fillRect(10,10,50,50);
6,图形组合
context.globalCompositeOperation=type
图形组合就是两个图形相互叠加了图形的表现形式,是后画的覆盖掉先画的呢,还是相互重叠的部分不显示等等,至于怎么显示就取决于type的值了
(source:最新绘制的图案 destination:原图案)
type:
source-over(默认值):在原有图形上绘制新图形(最新绘制图案在上)
destination-over:在原有图形下绘制新图形(原图案在上)
source-in:显示原有图形和新图形的交集,新图形在上,所以颜色为新图形的颜色(后绘制图案重叠部分)
destination-in:显示原有图形和新图形的交集,原有图形在上,所以颜色为原有图形的颜色(原图案重叠部分)
source-out:只显示新图形非交集部分(后绘制图案非重叠部分)
destination-out:只显示原有图形非交集部分(原图案非重叠部分)
source-atop:显示原有图形和交集部分,新图形在上,所以交集部分的颜色为新图形的颜色(后绘制图案重叠部分(上)与原图案)
destination-atop:显示新图形和交集部分,新图形在下,所以交集部分的颜色为原有图形的颜色(原图案重叠部分(上)与后绘制图案)
lighter:原有图形和新图形都显示,交集部分做颜色叠加(重叠部分颜色叠加)
xor:重叠飞部分不显示
copy:只显示新图形
7,图形绘制阴影
context.shadowOffsetX :阴影的横向位移量(默认值为0)
context.shadowOffsetY :阴影的纵向位移量(默认值为0)
context.shadowColor :阴影的颜色
context.shadowBlur :阴影的模糊范围(值越大越模糊)
var ctx = c.getContext("2d"); var grd = ctx.createLinearGradient(10,10,200,10); grd.addColorStop(0,"purple"); grd.addColorStop(0.25,"yellow"); grd.addColorStop(0.5,"orange"); grd.addColorStop(1,"red"); ctx.shadowOffsetX = 10; ctx.shadowOffsetY = 10; ctx.shadowColor = "rgba(0,0,0,0.3)"; ctx.shadowBlur = 2.0; ctx.font = "40px Arial"; ctx.fillStyle = grd; ctx.fillText("hello word!",10,60);//ctx.fillText("hello word!",x,y);x,y开始绘制文本的点
8,绘制图像
绘图:context.drawImage
图像平铺:context.createPattern(image,type)
图像裁剪:context.clip()
像素处理:var imagedata=context.getImageData(sx,sy,sw,sh)
绘图 context.drawImage
context.drawImage(image,x,y)
image:Image对象var img=new Image(); img.src="url(...)";
x:绘制图像的x坐标
y:绘制图像的y坐标
context.drawImage(image,x,y,w,h)
image:Image对象var img=new Image(); img.src="url(...)";
x:绘制图像的x坐标
y:绘制图像的y坐标
w:绘制图像的宽度
h:绘制图像的高度
context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh):
选取图像的一部分矩形区域进行绘制
image:Image对象var img=new Image(); img.src="url(...)";
sx:图像上的x坐标
sy:图像上的y坐标
sw:矩形区域的宽度
sh:矩形区域的高度
dx:画在canvas的x坐标
dy:画在canvas的y坐标
dw:画出来的宽度
dh:画出来的高度
最后一个方法可能比较拗,还是上图吧
var img =new Image(); img.src = "../images/11.png"; ctx.drawImage(img,0,0);
图像平铺 context.createPattern(image,type)
type:
no-repeat:不平铺
repeat-x:横方向平铺
repeat-y:纵方向平铺
repeat:全方向平铺
图像裁剪:context.clip()
context.clip()只绘制封闭路径区域内的图像,不绘制路径外部图像,用的时候
先创建裁剪区域
create5StarClip(ctx); var img =new Image(); img.src = "../images/11.png"; ctx.drawImage(img,0,0);
function create5StarClip(context) { var n = 0; var dx = 100; var dy = 100; var s = 100; context.beginPath(); //context.strokeStyle ="red"; 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.clip(); }
9,像素处理:
获取像素颜色数组: var imagedata=context.getImageData(sx,sy,sw,sh)
sx:cavas的x轴坐标点
sy:canvas的y轴坐标点
sw:距离x的宽度
sh:距离y的高度
可以利用context.getImageData返回的一个像素颜色数组,顺序是所取像素范围的从左到右,从上到下,数组的元素是(所有图形,包括图片,和绘制的图形)每个像素的rgba
[r1,g1,b1,a1,r2,g2,b2,a2...]
设置像素颜色:context.putImageData(imagedata,dx,dy,dirtyX,dirtyY,dirtyWidth,dirtyHeight)
对imagedata数组中的各个像素的r、g、b、a值进行修改,再调用putImageData方法进行绘制
imagedata:修改后的imagedata
dx:重绘图像的起点横坐标(重绘的起点和原来的图像一致的话就会把原来的图形覆盖掉,看起来就像是原来的图像变成现在的图像一样)
dy:重绘图像的起点纵坐标
//以下可选参数,设置重绘的矩形范围,如果缺省,默认会重绘所有的imegedata
dirtyX:矩形左上角x轴坐标
dirtyY:矩形左上角y轴坐标
dirtyWidth:矩形长度
dirtyHeight:矩形高度
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 function draw16(id) {
2 var canvas = document.getElementById(id);
3 if (canvas == null)
4 return false;
5 var context = canvas.getContext("2d");
6 context.fillStyle = 'red'
7 //在右下角画一个正方形
8 context.fillRect(250,250,150,50);
9 var image = new Image();
10 image.src = "Image/html5.jpg";
11
12 image.onload = function () {
13 //在左上角画一幅图片
14 context.drawImage(image, 0, 0,200,200);
15
16 //实验证明imagedata取的是canvas所在范围画的图形,不止是图片
17 //不会取该区域内是空白的canvas的像素
18 var imagedata = context.getImageData(0, 0, 400, 300);
19
20 //修改imagedata
21 for (var i = 0, n = imagedata.data.length; i < n; i += 4) {
22
23 imagedata.data[i + 0] = 255 - imagedata.data[i + 0]; //red;
24 imagedata.data[i + 1] = 255 - imagedata.data[i + 1]; //green
25 imagedata.data[i + 2] = 255 - imagedata.data[i + 2]; //blue
26 //imagedata.data[i + 3] = 255 - imagedata.data[i + 3]; //a
27 }
28 context.putImageData(imagedata, 0, 0);
29 }
30 }
10,保存和恢复状态
保存:context.save()
恢复:context.restore()
在上面的裁剪图片提过,一旦设定了裁剪区域,后来绘制的图形都只显示裁剪区域内的内容,要“取消”这个裁剪区域才能正常绘制其他图形,其实这个“取消”是利用save()方法和restore()方法来实现的。
context.save():调用该方法,会保存当前context的状态、属性(把他理解成游戏存档)
context.restore():调用该方法就能恢复到save时候context的状态、属性(游戏回档)
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 function draw18(id) {
2 var canvas = document.getElementById(id);
3 if (canvas == null)
4 return false;
5 var context = canvas.getContext("2d");
6 context.fillStyle = "red";
7 context.save(); //保存了当前context的状态
8 context.fillStyle = "black";
9 context.fillRect(0, 0, 100, 100);
10 context.restore();//恢复到刚刚保存的状态
11 context.fillRect(0,120,100,100);
12 }
11,保存文件 canvas.toDataURL(MIME)
在canvas中绘出的图片只是canvas标签而已,并非是真正的图片,是不能右键,另存为的,我们可以利用canvas.toDataURL()这个方法把canvas绘制的图形生成一幅图片,生成图片后,就能对图片进行相应的操作了。
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
1 function draw19(id) {
2 var canvas = document.getElementById(id);
3 if (canvas == null)
4 return false;
5 var context = canvas.getContext("2d");
6 context.fillStyle = "rgb(0,0,225)";
7 context.fillRect(0, 0, canvas.width, canvas.height);
8 context.fillStyle = "rgb(255,255,0)";
9 context.fillRect(10, 20, 50, 50);
10 //把图像保存到新的窗口
11 var w=window.open(canvas.toDataURL("image/jpeg"),"smallwin","width=400,height=350");