HTML Canvas
坐标体系:矩形区域的左上角为坐标原点(0,0),向右为x轴,向下为y轴。
检测浏览器是否支持Canvas(IE系列从IE9开始支持):
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 if(!document.createElement("canvas").getContext){ 8 alert("浏览器不支持Canvas"); 9 } 10 //]]> 11 </script> 12 </head> 13 <body> 14 </body> 15 </html>
Canvas的各种属性表:
属性名称 | 描述 | |
fillStyle | 填充属性 | 可以为一个字符串颜色值,也可以为gradient对象,或者pattern对象 |
strokeStyle | 绘制属性 | 可以为一个字符串颜色值,也可以为gradient对象,或者pattern对象 |
font | 字体样式定义 | |
globalAlpha | 图形透明设置 | |
globalCompositeOperation | 前后绘制的图形组合显示效果 | |
lineCap | 线帽 | |
lineJoin | 两条线段连接处的样式 | |
lineWidth | 线宽 | 为一个数字 |
miterLimit | 定义斜连接线和线条宽度的最大比率,这个属性只有当lineJoin="miter"时才有用 | |
shadowBlur | 阴影模糊 | |
shadowColor | 阴影色彩 | |
shadowOffsetX | 阴影横向偏移 | |
shadowOffsetY | 阴影纵向偏移 | |
textAlign | 文本水平对齐 | "start","end","left","right","center" |
textBaseline | 文本垂直对齐 | "aplhabetic","top","hanging","middle","ideographic","bottom" |
对于有global的属性都是全局属性,在使用的时候注意要先save()再restore()配置。
Canvas中的保存和回复
通过save()方法保存渲染上下文,通过restore()方法恢复上次保存的渲染上下文。
Canvas中的线
一个路径绘制通常会在beginPath()和closePath()之间完成;通过stroke()来执行实际的绘制。
弧度:一个圆一周的弧度为2π,一周的角度为360。
绘制弧线的arc()方法需要指定(圆心位置x,圆心位置y,半径,起始弧度,结束弧度,绘图方向),以圆心画弧;
绘制弧线的arcTo()方法需要指定(两条线的交点X,两条线的交点Y,其中一条线的经过点X,其中一条线的经过点Y,弧线半径),以相交线画弧。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 g.strokeStyle="#09f"; 15 g.lineWidth=2; 16 17 g.beginPath(); 18 19 g.moveTo(10,10); 20 g.lineTo(100,100); 21 g.lineTo(0,100); 22 23 // 圆心X位置,原型Y位置,半径,起始弧度,结束弧度,是否逆时针. 24 g.arc(0,100,50,-2*Math.PI*(45/360),2*Math.PI*(270/360),true); 25 // 以50,50作为两条线的焦点,两条线分别经过上次绘图的结束点和0,0参数点,并以10为半径的曲线. 26 g.arcTo(50,50,0,0,10); 27 28 g.stroke(); 29 g.closePath(); 30 } 31 //]]> 32 </script> 33 </head> 34 <body> 35 </body> 36 </html>
二次方曲线quadraticCurveTo(控制点X坐标,控制点Y坐标,结束点X坐标,结束点Y坐标) 通过一个控制点来绘制曲线:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 g.strokeStyle="#09f"; 15 g.lineWidth=2; 16 17 g.beginPath(); 18 19 g.moveTo(0,100); 20 g.quadraticCurveTo(50,0,100,100); 21 g.stroke(); 22 g.closePath(); 23 } 24 //]]> 25 </script> 26 </head> 27 <body> 28 </body> 29 </html>
贝塞尔曲线bezierCurveTo()方法比quadraticCurveTo()方法多一个控制点:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 g.strokeStyle="#09f"; 15 g.lineWidth=2; 16 17 g.beginPath(); 18 19 g.moveTo(0,100); 20 g.bezierCurveTo(50,0,75,125,100,100); 21 g.stroke(); 22 g.closePath(); 23 } 24 //]]> 25 </script> 26 </head> 27 <body> 28 </body> 29 </html>
Canvas没有专门绘制圆的API,可以通过arc()来绘制,再通过filleStyle属性来设置填充,并通过fill()来关闭路径并填充。
Canvas中的矩形
用fillRect()指定左上角和右下角指定下矩形,fileRect()调用的时候会星清晰化路径;
用strokeRect()可以绘制一个矩形的边框,该方法也会清晰化路径。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 g.strokeStyle="#09f"; 15 g.fillStyle="green"; 16 g.lineWidth=2; 17 18 g.beginPath(); 19 g.moveTo(0,100); 20 g.lineTo(50,50); 21 g.fillRect(100,100,50,50); 22 // 对于2px像素的线宽,在绘制的时候会两边平分1像素,同时canvas的默认画布大小为300*150px 23 // 这里可以看到绘制出的矩形边框的右边和下边只有1像素. 24 g.strokeRect(100,120,200,30); 25 g.lineTo(50,100); 26 g.stroke(); 27 g.closePath(); 28 } 29 //]]> 30 </script> 31 </head> 32 <body> 33 </body> 34 </html>
Canvas中的图片
在Canvas中可以使用drawImage()方法或者createPattern()方法来绘制图片。
drawImage有3种参数格式:drawImage(img,x,y); drawImage(img,x,y,w,h);
drawImage(img,s1x,s1y,s2w,y2h,d1x,d1y,d2w,d2h);
createPattern(img,css-position)方法主要用于背景图片的处理,第二个参数很像CSS中的background-position属性。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 var img=new Image(); 15 img.onload=function(){ 16 g.drawImage(img,10,10,16,16); 17 } 18 img.src="http://files.cnblogs.com/xf_z1988/ico.ico"; 19 } 20 //]]> 21 </script> 22 </head> 23 <body> 24 </body> 25 </html>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 var img=new Image(); 15 img.onload=function(){ 16 g.fillStyle=g.createPattern(img,‘repeat‘); 17 g.fillRect(0,0,300,150); 18 } 19 img.src="http://files.cnblogs.com/xf_z1988/ico.ico"; 20 } 21 //]]> 22 </script> 23 </head> 24 <body> 25 </body> 26 </html>
Canvas中的文字
Canvas中文字有两种显示方式,一种用fillText()方法,另一种用strokeText()方法,同绘制矩形的API很像。
绘制前可以设置font、textAlign、textBaseline属性来控制绘制文字。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 g.fillStyle="#09f"; 15 g.strokeStyle="green"; 16 g.font="bold 14px Arial"; 17 g.textBaseline="top"; 18 var textAlign_v=["start","end","left","right","center"]; 19 for(var i=0,j=textAlign_v.length;i<j;++i){ 20 g.fillRect(i*40,0,1,150); 21 g.textAlign=textAlign_v[i]; 22 g.fillText("ZXF",i*40,i*14); 23 } 24 g.textAlign="left"; 25 var textBaseline_v=["aplhabetic","top","hanging","middle","ideographic","bottom"]; 26 g.fillRect(0,100,300,1); 27 for(var i=0,j=textBaseline_v.length;i<j;++i){ 28 g.textBaseline=textBaseline_v[i]; 29 g.strokeText("ZXF",i*40,100); 30 31 } 32 } 33 //]]> 34 </script> 35 </head> 36 <body> 37 </body> 38 </html>
Canvas中的渐变
通过createLinearGradient(x1,y1,x2,y2)或createRadialGradient(xo1,yo1,r1,xo2,yo2,r2)这两个方法创建渐变。
通过gdt.addColorStop()方法来添加颜色。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 var gradient_l=g.createLinearGradient(0,0,150,100); 15 gradient_l.addColorStop("0","green"); 16 gradient_l.addColorStop("0.5","red"); 17 gradient_l.addColorStop("1","yellow"); 18 g.fillStyle=gradient_l; 19 g.fillRect(0,0,150,100); 20 g.fillRect(150,100,150,50); 21 } 22 //]]> 23 </script> 24 </head> 25 <body> 26 </body> 27 </html>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 // 两圆外切就是色彩范围. 15 var gradient_r=g.createRadialGradient(40,40,30,50,50,40); 16 gradient_r.addColorStop("0","green"); 17 gradient_r.addColorStop("0.5","red"); 18 gradient_r.addColorStop("1","yellow"); 19 g.fillStyle=gradient_r; 20 g.fillRect(0,0,150,150); 21 22 var n2=document.createElement("canvas"); 23 document.body.appendChild(n2); 24 var g2=n2.getContext("2d"); 25 var gradient_r2=g2.createRadialGradient(40,40,20,50,50,40); 26 gradient_r2.addColorStop("0","green"); 27 gradient_r2.addColorStop("0.5","red"); 28 gradient_r2.addColorStop("1","yellow"); 29 g2.fillStyle=gradient_r2; 30 g2.fillRect(0,0,150,150); 31 } 32 //]]> 33 </script> 34 </head> 35 <body> 36 </body> 37 </html>
通过shadowOffsetX属性和shadowOffsetY属性设定阴影在X轴和Y轴的延伸,shadowBlur属性设置模糊,shadowColor属性设置模糊颜色。
Canvas中的坐标转换
通过translate(x,y)方法移动坐标,通过rotate(deg*Math.PI/180)方法来旋转坐标,通过scale(x,y)方法来缩放坐标。
另外一个transform(xscale,rotate,incline,yscale,x,y)方法可以进行变形操作。
translate(x,y)相当于transform(1,0,0,1,x,y);
scale(x,y)相当于transform(x,0,0,y,0,0);
rotate(a)相当于transform(cosA,sinA,-sinA,cosA,0,0)
Canvas中的组合
通过设置上下文的globalCompositeOperation属性来指定新图形绘制时按何种方式和已有图形组合。
copy | 只绘制新图形,删除其他所有内容 |
darker | 图形重叠的地方的颜色由两个颜色值相减后的值决定 |
destination-atop | 已有的内容只有在它和新图形重叠的地方保留。新图形绘制在内容之后。 |
destination-in | 新图形以及已有画布重叠的地方,已有内容都保留,所有其他内容成为透明。 |
destination-out | 新图像以及已有画布不重叠的地方,已有内容都保留,所有其他内容成为透明。 |
destination-over | 新图形绘制于已有内容的后面。 |
lighter | 图形重叠的地方的颜色由两个颜色值相加后的值决定 |
source-atop | 重叠的地方绘制新图形。 |
source-in | 新图形以及已有画布重叠的地方,绘制新图形,所有其他内容成为透明。 |
source-out | 新图像以及已有画布不重叠的地方,绘制新图形,所有其他内容成为透明。 |
source-over | 新图形绘制于已有图形的顶部,为默认行为。 |
xor | 在重叠和正常绘制的其他地方,图形都成为透明。 |
Canvas中的裁剪
使用clip()方法裁剪的区域之外的动画不受影响,该方法通过计算所有的子路径来建立新的剪切区域,
未闭合的子路径在填充区按照闭合方式填充,但并不影响实际的子路径集合,新的剪切区域将替换当前的剪切区域。
裁剪路径其实就是绘图路径,只不过这个路径不是拿来绘图的,而是设定显示区域和遮挡区域的一个分界线。
Canvas中的像素操作
可以通过createImageData(w,h)方法来创建一个全透明黑色的空白像素矩阵。
可以通过putImageData(canvasData,imgX,imgY,toX,toY,toW,toH)方法来将图像渲染到画布上。
当前通过putImageData()到画布上的图像不会受scale()等方法的影响。
可以通过getImageData(x,y,w,h)方法来获取Canvas中某一矩形区域的像素数据,像素数据按照RGBA方式排序。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script type="text/javascript"> 6 //<![CDATA[ 7 window.onload=function(){ 8 if(!document.createElement("canvas").getContext){ 9 return; 10 } 11 var n=document.createElement("canvas"); 12 document.body.appendChild(n); 13 var g=n.getContext("2d"); 14 var img=new Image(); 15 img.onload=function(){ 16 g.drawImage(img,0,0,300,150); 17 var img_new=g.createImageData(300,150); 18 var img_data=img_new.data; 19 var data=g.getImageData(0,0,300,150).data; 20 var wd=300; 21 for(var i=0,j=data.length;i<j;i+=1){ 22 // 透明度为0则当作255白色 23 var ckop=(i+1)%4; 24 // 均值. 25 var t=(i>=wd*4)?(data[i-wd*4+ckop]==0&&ckop!=0?255:data[i-wd*4]):255; 26 var b=i<=j-wd*4?(data[i+wd*4+ckop]==0&&ckop!=0?255:data[i+wd*4]):255; 27 var l=i>=4?(data[i-4+ckop]==0&&ckop!=0?255:data[i-4]):255; 28 var r=i<=j-4?(data[i+4+ckop]==0&&ckop!=0?255:data[i+4]):255; 29 var now=data[i+ckop]==0&&ckop!=0?255:data[i]; 30 img_data[i]=Math.floor((t+b+now)/3); 31 } 32 n.onclick=function(){ 33 g.clearRect(0,0,300,150); 34 g.putImageData(img_new,0,0,10,10,300,150); 35 } 36 } 37 // 这里没有加载外域的图片.安全考虑.不能对外域图片进行像素操作. 38 img.src="data:image/gif;base64,R0lGODlhLAGWANUAAAAAAP///6UtMJ8qNJ0pNZ4qNZooN5knOIkgQoohQoQeRoMeRoAcSHsaS3gZTXcYTnYXT3MWUXIWUXIWUnEVUnAVU28UVG4UVO1OAO5OAOxNAehLBOdLBOVKBuRKBuRJB9xGDNdED9ZDENNCEtJBEtBBE9BAFM4/Fco+GMQ7HMI6HcA5Hr44H744ILU0JbU0JrIzKLEyKLAyKa8yKa4xKqwwK6swLP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADcALAAAAAAsAZYAAAb/wJtwSCwaj8ikcslsOp/QqHRKrVqv2Kx2y+16v+CweEwum8/otHrNbrvf8Lh8Tq/b7/i8fs/v+/+AgYKDhIWGh4iJiouMjY6PQhmSk5SUkJeYZpWbnJuZn6BVnaOkk6GnqEalq6yprpmssa2vtIqyt7O1uoG4vbm7wHi+w7/Bxm/EycXHzGfKz6XN0prQ1Z3T2F/W26PZ3ljc4Zzf5FLi55Xl6kzo7abr8EXu8xnx9vT09uv4+Prl/Pn8eQPYT+A0gvwMNkMIUKGgCxAjSpQ4hWFCh3smatyosYnFhhjtcBxJMqKSjxdDxinJsqUqlClVsmlJ02UkmCBlpqnJ0yXO/5w6y/QcWnLGT6BBwxBdujHCh6Mxk3phSnViAahRpW6pyhWiCaxZtV7pypUB2LBiqZDlauNswbRW1nYV4fYtXClyuTbAUDfg3Sh5uQ7o6/fvk8BVWxAubHgJ4qogFs9r3OQxVQiSJ1NWYpkqgszuNifpTJUA6HaikZBmKuM06tREVjNN4Rod7CGymZKofe62kNxLI/MO5xv40g7Did82TpRDcm7LmQ99Dh229OnUrVm/3tN5dmjbuddE/v1ZePEthZdPlho9zxHrlbV3T5N2fGLz6bOMcR//Zv00mdZfL/kBSNJnA+JSoIEcYZbgLQsyuJF6D64SoYQTsVBhLKJhWP/SYBtG06GHI+0VIikXkhgRXSdeM6KKG9XQ4jgpwmjWjOnUCGMJOFqio4pX9VjPeTBO5JSQ0RW5EQ1IEqlkRA5sgGNxT27E34xUVjnRAx606NsNWm4kwIlfghnmRBWEEGKZZp4ZUQIaVMhmm25C5IKcbNYp0QRqDjgnnXouIOV9fwKq5wF8rVfob3pKBEN8ixpapwUrlBeppHVSgEJ2lzLaaEQRnPBcp55+ClEEm/JGaqmmXkCBCrWtilurEVlwZWayzkprRAYM2leuRewqkQJ9ugVssMJGJMELiWJ1rBHJUuTss9BGC9EQOFE7WrTyfKQtZ8ImgdS3RyS7hGbkMrF/6xPKpXuYqRXJ5+4Un2bB4bxY6IkvIPru+4eb/gYSZsCDKElwITAebAiJCh+CYcOJAAjxIvRN3Ah3FkNiXMaZrMbxKYF9TAtXIh9DU8kop6zyyiy37PLLMMcs88w012zzzTjnrPPOPPfs889ABy300EQXbfTRSCet9NJMNx1PEAA7"; 39 } 40 //]]> 41 </script> 42 </head> 43 <body> 44 </body> 45 </html>
JavaScript & HTML5 Canvas 概览 更新时间2014-0411-1805,布布扣,bubuko.com