感性认识
canvas元素是HTML5中新增的一个重要元素,专门用来绘制图形,它就像页面的一个画布,利用canvas绘图的步骤很简单:
- 页面放置canvas;
- 获取canvas的context;
- 通过context的api用JavaScript来进行绘画;
- 绘制路径(矩形不需要),设置样式,使用stroke或fill来填充;
首先我们了解canvas的坐标是这样的
先来看下示例
绘制的图形如下:
绘制简单图形
- 绘制矩形
fillRect(x, y, width, height) //绘制实心矩形,被填充strokeRect(x, y, width, height)//绘制空心矩形,只是边框
- 绘制圆形矩形不用绘制路径,直接fill或stroke,而其他的图形需要先绘制路径,然后在fill或stroke。
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
- x:圆的中心的 x 坐标。
- y:圆的中心的 y 坐标。
- r:圆的半径。
- sAngle:起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
- eAngle:结束角,以弧度计。
- counterclockwise:可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。
- 绘制直线
ctx.moveTo(200,30); //设置路径的起点ctx.lineTo(280,60); //设置路径的终点ctx.stroke(); //给路径着色
绘制渐变
- 线性渐变 示例:
var canvas=document.getElementById("mycanvas");//获取contextvar ctx=canvas.getContext("2d");//设置样式ctx.lineWidth=20;var g=ctx.createLinearGradient(0,0,0,100);g.addColorStop(0,'green');g.addColorStop(0.5,'blue');g.addColorStop(1,'red');ctx.strokeStyle=g;ctx.moveTo(0,0);ctx.lineTo(0,100);ctx.stroke();
context.createLinearGradient(x0,y0,x1,y1);
- x0:渐变开始点的 x 坐标
- y0:渐变开始点的 y 坐标
- x1:渐变结束点的 x 坐标
- y1:渐变结束点的 y 坐标
gradient.addColorStop(stop,color);
- stop:介于 0.0 与 1.0 之间的值,表示渐变中开始与结束之间的位置。
- color:在结束位置显示的 CSS 颜色值
- 径向渐变 示例
context.createRadialGradient(x0,y0,r0,x1,y1,r1);
- x0:渐变的开始圆的 x 坐标
- y0:渐变的开始圆的 y 坐标
- r0:开始圆的半径
- x1:渐变的结束圆的 x 坐标
- y1:渐变的结束圆的 y 坐标
- r1:结束圆的半径
绘制变形图
- 坐标变换 可以通过变化canvas坐标来达到变换图形的效果,坐标有三种变换方式:
- 平移:重新映射画布上的 (0,0) 位置
context.translate(x,y);
- 缩放:缩放当前绘图至更大或更小
context.scale(x,y);
- 旋转:旋转当前绘图
context.rotate(angle);
- 平移:重新映射画布上的 (0,0) 位置
- 坐标变换和路径结合的使用 路径一旦绘制好后是不会随着坐标变换而变换的,如
var canvas=document.getElementById("mycanvas");//获取contextvar ctx=canvas.getContext("2d");//坐标变换前的路径ctx.moveTo(0,0);ctx.lineTo(100,20);ctx.lineTo(20,80);//变换坐标ctx.rotate(20*Math.PI/180);//为路径填色ctx.strokeStyle="green";ctx.stroke();//坐标变换后绘制的图像,路径与上一路径相同ctx.strokeStyle="red";ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(100,20);ctx.lineTo(20,80);ctx.stroke();
var canvas=document.getElementById("mycanvas");//获取contextvar ctx=canvas.getContext("2d");doPic(ctx,"green");ctx.rotate(20*Math.PI/180);doPic(ctx,"red");ctx.rotate(20*Math.PI/180);doPic(ctx,"blue");function doPic(ctx,color){ ctx.beginPath(); ctx.moveTo(0,0); ctx.lineTo(100,20); ctx.lineTo(20,80); ctx.strokeStyle=color; ctx.stroke(); }
- 矩阵变换 如果上述都不能满足需求,HTML5还提供一种更复杂的变化:矩阵变换,这块牵涉到矩阵的数学知识,稍后单一节示例。
图像组合
通常当绘制的图像重叠时将以绘制的先后顺序来处理重叠的部分,但HTML5提供了globalCompositeOperation 选项来设置如何处理重叠。
绘制的图像
globalCompositeOperation 属性设置或返回如何将一个源(新的)图像绘制到目标(已有)的图像上。
- 源图像 = 您打算放置到画布上的绘图。
- 目标图像 = 您已经放置在画布上的绘图。
属性值和描述
- source-over:默认。在目标图像上显示源图像。
- source-atop:在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
- source-in:在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
- source-out:在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
- destination-over:在源图像上方显示目标图像。
- destination-atop:在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
- destination-in:在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
- destination-out:在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
- lighter:显示源图像 + 目标图像。
- copy:显示源图像。忽略目标图像。
- source-over:使用异或操作对源图像与目标图像进行组合。
绘制阴影
HTML5给添加阴影也非常简单,主要涉及到下面几个属性:
- shadowColor:设置或返回用于阴影的颜色,如果取消只需设置为rgba(0,0,0,0);
- shadowBlur:设置或返回用于阴影的模糊级别,一般设置在0-10之间;
- shadowOffsetX:设置或返回阴影距形状的水平距离;
- shadowOffsetY:设置或返回阴影距形状的垂直距离;
ctx.fillStyle="blue";ctx.shadowColor="#ccc";ctx.shadowBlur=5;ctx.shadowOffsetX=10;ctx.shadowOffsetY=10;ctx.fillRect(10,10,60,60);ctx.fillRect(80,80,60,60);
使用图片
-
- 绘制图片 插入图片的方法只有一个,但是有三个重载方法,具体如下:
context.drawImage (image, dx, dy)context.drawImage (image, dx, dy, dw, dh)context.drawImage (image, sx, sy, sw, sh, dx, dy, dw, dh)
- 绘制图片 插入图片的方法只有一个,但是有三个重载方法,具体如下:
createPattern(image, repetitionStyle)
-
- 创建并返回一个 CanvasPattern 对象,该对象表示一个贴图图像所定义的模式。要使用一个模式来勾勒线条或填充区域,可以把一个 CanvasPattern 对象用作 strokeStyle 属性或 fillStyle 属性的值。repetitionStyle 说明图像如何贴图。可能的值如下所示:
- "repeat" - 在各个方向上都对图像贴图。默认值。
- "repeat-x" - 只在 X 方向上贴图。
- "repeat-y" - 只在 Y 方向上贴图。
- "no-repeat" - 不贴图,只使用它一次。
img.οnlοad=function(){ var ptt=ctx.createPattern(img,'repeat'); ctx.fillStyle=ptt; ctx.fillRect(0,0,300,200);}
- 裁剪 clip() 方法从原始画布中剪切出任意形状和尺寸。 一旦再勾画出路径后调用clip方法,则所有只有的绘图都会被限制在这个路径区域,从而达到裁剪的效果,可以结合save和restore方法。
img.οnlοad=function(){ ctx.beginPath(); ctx.arc(60,60,50,0,Math.PI*2,true); ctx.clip(); ctx.drawImage(img,0,0);}
- 像素 html5还有一个令人赞叹的技术就是可以处理像素,这设计到两个API:
var imgData=context.getImageData(x,y,width,height);
- x - 开始复制的左上角位置的 x 坐标。
- y - 开始复制的左上角位置的 y 坐标。
- width - 将要复制的矩形区域的宽度。
- height - 将要复制的矩形区域的高度。
- r - 红色 (0-255)
- g - 绿色 (0-255)
- b - 蓝色 (0-255)
- a - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
- imgData - 规定要放回画布的 ImageData 对象。
- x - ImageData 对象左上角的 x 坐标,以像素计。
- y - ImageData 对象左上角的 y 坐标,以像素计。
- dirtyX - 可选。水平值(x),以像素计,在画布上放置图像的位置。
- dirtyY - 可选。水平值(y),以像素计,在画布上放置图像的位置。
- dirtyWidth - 可选。在画布上绘制图像所使用的宽度。
- dirtyHeight - 可选。在画布上绘制图像所使用的高度。
img.οnlοad=function(){ ctx.drawImage(img,0,0); var imgData=ctx.getImageData(10,10,80,80); for(var i=0;i
绘制文字
在canvas中也可以绘制文字,这涉及到两个API:
context.fillText(text,x,y,maxWidth);context.strokeText(text,x,y,maxWidth);
- text - 规定在画布上输出的文本。
- x - 开始绘制文本的 x 坐标位置(相对于画布)。
- y - 开始绘制文本的 y 坐标位置(相对于画布)。
- maxWidth - 可选。允许的最大文本宽度,以像素计。
在绘制之前可以先设置文字的相关属性:
- font属性:设置文字的字体,语法与 CSS font 属性相同,可以按顺序设置font-style、font-variant、font-weight、font-size/line-height、font-family;
- textAlign属性:设置文字的水平对齐方式,可选值start、end、left、right、center,默认是start;
- textBaseline属性:设置文字的垂直对齐方式,可选值top、hanging、middle、alphabetic、ideographic、bottom,默认是alphabetic;
有时为了方便定位,需要获取文字的宽度,html5提供了一个API:
context.measureText(text)
返回的TextMetrics对象的width属性表示使用当前指定的字体后文字的总长度。
ctx.font="italic 30px sans-serif";ctx.textBaseline="top";ctx.fillStyle="red";var txt='爱我中华';ctx.fillText(txt,0,0);var tml = ctx.measureText(txt);ctx.strokeStyle="green";ctx.strokeText(txt,tml.width+20,0);
善后工作
- 保存及恢复状态 在绘制过程中,可能临时要改变一下属性设置,当临时绘制结束又想回到之前的状态,这就涉及到恢复,涉及到两个API:
save() //把当前环境的状态压入栈restore() //状态出栈
ctx.fillText(txt,0,0);ctx.save();//状态入栈ctx.fillStyle="green";ctx.textBaseline="bottom";ctx.fillText(txt,0,80);ctx.restore();//状态出栈ctx.fillText(txt,0,120);
- 保存文件 在canvas绘制后可以使用toDataURL方法把它保存成浏览器能识别的data URL数据
ctx.font="italic 30px sans-serif";ctx.textBaseline="top";ctx.fillStyle="red";var txt='爱我中华';ctx.fillText(txt,0,0);document.getElementById("img").src=mycanvas.toDataURL("image/jpeg");
- 简单动画 可以在canvas重复绘制、擦除、绘制的动作来实现动画,这其中涉及到一个擦除的API
context.clearRect(x,y,width,height);
setInterval(code,millisec[,"lang"])
var i=0;var intervalId=setInterval(doarc,1000);function doarc(){ ctx.clearRect(0,0,mycanvas.width,mycanvas.height); ctx.beginPath(); ctx.arc(i,i,20,20,Math.PI*2,true); ctx.fillStyle="blue"; ctx.fill(); i+=30; if(i>200){clearInterval(intervalId);}}