Canvas是HTML5添加的新元素,这个元素负责在页面中设定一个区域,然后通过JavaScript动态的在这个区域绘制图形。<canvas>由几组API组成,除了具备基本绘图能力的2D上下文,<canvas>还建议了一个名为WebGL的3D上下文,目前,支持该元素的浏览器都支持2D上下文,但对WebGL的支持还不够好。以下仅介绍2D上下文。
一、2D上下文
1、进行填充和描边
2D上下文的两种基本绘图操作是填充和描边;填充,是指的用指定的样式填充图形;描边,就是只在图像边缘划线。下例中绘制的矩形,是唯一一种可以直接在2D上下文绘制的图形。
<!doctype html> <html> <head> <meta charset = "utf-8"> <title>填充和描边</title> </head> <body> <!-- 出现在开始和结束标签中的是后备信息,如果浏览器不支持,就会显示: A drawing of something.--> <canvas id="drawing" height="400" width="400">A drawing of something.</canvas> <script> var drawing = document.getElementById("drawing"); // 确认浏览器支持canvas元素 if(drawing.getContext){ 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.clearRect(40,40,10,10); // 绘制红色描边的矩形 context.strokeStyle = "#ff0000"; context.strokeRect(50,50,50,50); // 绘制半透明蓝色描边的矩形 context.strokeStyle = "rgba(0,0,255,0.5)"; context.strokeRect(70,70,50,50); } </script> </body> </html>
2、绘制路径和文本
2D上下文支持很多在画布上绘制路径的方法,通过路径可以创建出复杂的线条的形状。
<!doctype html> <html> <head> <meta charset = "utf-8"> <title>绘制路径和文本</title> </head> <body> <!-- 出现在开始和结束标签中的是后备信息,如果浏览器不支持,就会显示: A drawing of something.--> <canvas id="drawing" height="400" width="400">A drawing of something.</canvas> <script> var drawing = document.getElementById("drawing"); // 确认浏览器支持canvas元素 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); // 确定路径被关闭前,某一点是否在路径上 if(context.isPointInPath(100,100)){ // alert("Point (100,100) is not in the path"); } // 描边路径 context.stroke(); //--------------------------------------------------------------------------------- // 绘制文本 context.font = "bold 14px Arial"; context.textAlign = "center"; //正常 context.textBaseline = "middle"; context.fillText("12",100,20); context.textAlign = "start"; //x表示的是文本的起始位置 context.fillText("12",100,40); context.textAlign = "end"; //x表示的是文本的结束位置 context.fillText("12",100,60); //------------------------------------------------------------------------------ // 如果要在140px宽的区域中绘制文本,下面的像素从100px开始递减,最终找到合适的字体大小 var fontSize = 100; context.font = fontSize+"px Arial"; while(context.measureText("Hello World").width > 140){ fontSize--; context.font = fontSize+"px Arial"; } context.fillText("Hello World", 210,210); } </script> </body> </html>
3、变换
2D上下文支持各种基本的绘制变换;创建绘制上下文时,会以默认值初始化变换矩阵;使用不同的变换矩阵应用处理,会产生不同的结果。
<!doctype html> <html> <!-- 2D绘制上下文支持以下的绘制变换 rotate(angle):围绕原点旋转图像angle角度 scale(scaleX, scaleY):缩放图像,在x轴上乘以scaleX, 在Y轴上乘以scaleY translate(x, y):将原点坐标移动到x,y transform(m1_1, m1_2, m2_1, m2_2, dx, dy):乘以如下变换矩阵 m1_1 m1_2 dx m2_1 m2_2 dy 0 0 1 setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):先将变换矩阵重置为默认状态,再调用transform --> <head> <meta charset = "utf-8"> <title>旋转时钟的指针</title> </head> <body> <!-- 出现在开始和结束标签中的是后备信息,如果浏览器不支持,就会显示: A drawing of something.--> <canvas id="drawing" height="400" width="400">A drawing of something.</canvas> <script> var drawing = document.getElementById("drawing"); // 确认浏览器支持canvas元素 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.translate(100,100); // 旋转表针 context.rotate(1); // 绘制分针 context.moveTo(0,0); context.lineTo(0,-85); // 绘制时针 context.moveTo(0,0); context.lineTo(-65,0); context.stroke(); } </script> </body> </html>
4、绘制图像和模式
2D上下文内置了对图像的支持;模式实际上是重复的图像,可以用来填充或描边图形。
<!doctype html> <html> <head> <meta charset = "utf-8"> <title>绘制图像/模式</title> </head> <body onload="drawPic()"> <img src="data:image1.png" alt="" id="myImg"/> <canvas id="drawing" height="400" width="400" style="border:1px solid #d3d3d3;">A drawing of something.</canvas> <script> function drawPic(){ var drawing = document.getElementById("drawing"); var image = document.getElementById("myImg"); // 确认浏览器支持canvas元素 if(drawing.getContext){ // 绘制图片 var context = drawing.getContext("2d"); context.drawImage(image, 50,10,20,30); // 使用模式重复绘制图片 // 创建模式,在一个矩形区域重复显示图像 var pattern = context.createPattern(image, "repeat"); context.fillStyle = pattern; context.fillRect(100,100,100,100); } } </script> </body> </html>
5、阴影和渐变
不同浏览器对阴影的支持有一些差异,有些甚至根本不支持阴影;可以通过createLinearGradient和createRadialGradient创建线性渐变和径向渐变。
<!doctype html> <html> <head> <meta charset = "utf-8"> <title>阴影和渐变</title> </head> <body> <canvas id="drawing" height="400" width="400" style="border:1px solid #d3d3d3;">A drawing of something.</canvas> <script> var drawing = document.getElementById("drawing"); var context = drawing.getContext("2d"); //设置阴影 context.shadowOffsetX = 5; //x轴方向的阴影偏移量 context.shadowOffsetY = 5; //y轴方向的阴影偏移量 context.shadowBlur = 4; //模糊的像素数 context.shadowColor = "rgba(0,0,0,0.5)"; //阴影的颜色 context.fillStyle = "#ff0000"; context.fillRect(10,10,50,50); context.fillStyle = "rgba(0,0,255,1)"; context.fillRect(30,30,50,50); // 设置线性渐变 var gradient = context.createLinearGradient(100,100,150,150); gradient.addColorStop(0,"white"); gradient.addColorStop(1,"black"); context.fillStyle = gradient; context.fillRect(100,100,50,50); // 设置径向渐变 gradient = context.createRadialGradient(175,175,10,175,175,30); gradient.addColorStop(0,"white"); gradient.addColorStop(1,"black"); context.fillStyle = gradient; context.fillRect(150,150,50,50); </script> </body> </html>
6、使用图像数据
2D上下文可以通过getImageData()取得原始图像数据,并对其中的每一个像素进行处理;注意这个函数操作的图像和html文件需要在同一个域,否则会有跨域问题。下例是一个简单的灰阶过滤器。
<!doctype html> <html> <head> <meta charset = "utf-8"> <title>灰阶过滤器</title> </head> <body onload = "filter()"> <img src="data:image1.png" alt="" id="myImg"/> <canvas id="drawing" height="400" width="400" style="border:1px solid #d3d3d3;">A drawing of something.</canvas> <script> function filter(){ var drawing = document.getElementById("drawing"); if(drawing.getContext){ var context = drawing.getContext("2d"), image = document.images[0]; // 绘制原始图像 context.drawImage(image, 0,0); // 取得图像数据 var imageData = context.getImageData(0,0,image.width,image.height); var data = imageData.data; for(var i = 0, len = data.length;i<len;i+=4){ // 每个data数组中,都有四个元素红、绿、蓝和透明度的值 var red = data[i], green = data[i+1], blue = data[i+2], alpah = data[i+3]; // 求rgb的平均值 var 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); } } </script> </body> </html>
7、合成
globalAlpha是一个介于0和1之间的值(包括0和1),用于指定所有绘制的透明度;globalCompositionOperation表示绘制后的图像怎么与先绘制的图形结合。
<!doctype html> <html> <head> <meta charset = "utf-8"> <title>合成</title> </head> <body> <canvas id="drawing" height="400" width="400" style="border:1px solid #d3d3d3;">A drawing of something.</canvas> <script> var drawing = document.getElementById("drawing"); if(drawing.getContext){ var context = drawing.getContext("2d"); context.fillStyle = "#ff0000"; context.fillRect(10,10,50,50); // 设置合成操作 context.globalCompositeOperation = "destination-over"; // 后绘制的图像位于先绘制的图像下方 context.fillStyle = "rgba(0,0,255,1)"; context.fillRect(30,30,50,50); } </script> </body> </html>