利用 Canvas 的 API,展示一些基本图形的绘制及操作方法,包括画线、画图、文字操作及图片操作等。(内含代码清单)
一、绘制基本图形
1.1 画线
简约版:
<!DOCTYPE HTML>
<html>
<body>
<canvas id="myCanvas" width="200" height="100">
你的浏览器不支持 HTML5
</canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.lineWidth = 10;
ctx.strokeStyle = "red";
ctx.beginPath();
ctx.moveTo(10,10);
ctx.lineTo(150,50);
ctx.stroke();
</script>
</body>
</html>
注释版:
<!DOCTYPE HTML>
<html>
<body>
/*在HTML中嵌入Canvas标签,如果浏览器不支持Canvas标签,那么浏览器会自动跳过Canvas标签,运行Canvas内部HTML代码*/
<canvas id="myCanvas" width="200" height="100">
你的浏览器不支持 HTML5
</canvas>
<script type="text/javascript">
/*获取HTML中的Canvas标签*/
var c=document.getElementById("myCanvas");
/*返回一个用来绘制环境类型的环境,目前只支持2d环境*/
var ctx=c.getContext("2d");
/*线宽*/
ctx.lineWidth = 10;
/*笔画颜色,这里颜色值可以是英文字母、RGB值、十六进制颜色*/
ctx.strokeStyle = "red";
/*线帽有三种,分别是butt、round、square
butt:默认。向线条的每个末端添加平直的边缘。
round:向线条的每个末端添加圆形线帽。
square:向线条的每个末端添加正方形线帽。*/
ctx.lineCup="butt";
/*创建一个新路径*/
ctx.beginPath();
/*画笔光标起始位置*/
ctx.moveTo(10,10);
/*画笔光标终止位置*/
ctx.lineTo(150,50);
/*开始绘制定义好的路径*/
ctx.stroke();
</script>
</body>
</html>
1.2 画矩形
空心矩形:
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.lineWidth = 10;
ctx.strokeStyle = "red";
ctx.beginPath();
/*用strokeRect函数绘制矩形,四个参数:起点坐标x、起点坐标y、矩形长、矩形宽*/
ctx.strokeRect(10,10,70,40);
</script>
注:ctx.strokeRect(10,10,70,40);
等价于ctx.rect(10,10,70,40);ctx.stroke();
实心矩形:
/*使用fillRect函数*/
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle = "red";
ctx.beginPath();
/*用strokeRect函数绘制矩形,四个参数:起点坐标x、起点坐标y、矩形长、矩形宽*/
ctx.fillRect(10,10,70,40);
</script>
注:ctx.fillRect(10,10,70,40);
等价于ctx.rect(10,10,70,40);ctx.fill();
1.3 画圆
圆其实就是360度的圆弧。在Canvas中,可使用arc函数来画一个圆弧。
空心圆:
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.lineWidth = 5;
ctx.strokeStyle = "red";
ctx.beginPath();
/*用arc函数绘制圆弧,六个参数:圆弧中心坐标x、圆弧中心坐标y、圆弧半径、起始角度、终止角度(要转化成弧度)、是否逆时针*/
ctx.arc(100,100,70,0,360*Math.PI/180,true);
ctx.stroke();
</script>
实心圆:
/*使用fill函数*/
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.lineWidth = 5;
ctx.strokeStyle = "red";
ctx.beginPath();
/*用arc函数绘制矩形,六个参数:圆弧中心坐标x、圆弧中心坐标y、圆弧半径、起始角度、终止角度(要转化成弧度)、是否逆时针*/
ctx.arc(100,100,70,0,360*Math.PI/180,true);
ctx.fill();
</script>
1.4 圆角矩形
Canvas中没有直接画圆角矩形的API,但是我么可以用arcTo函数完成圆角的绘制,然后结合直线绘制,就可以完成圆角矩形的绘制了。
绘制一个圆角:
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(70,20);
/*用arcTo函数为当前的子路径添加一条圆弧。5个参数:P1坐标x、P1坐标y、P2坐标x、P2坐标y、圆弧半径*/
ctx.arcTo(120,30,120,70,50);
ctx.lineTo(120,120);
ctx.stroke();
</script>
绘制圆角矩形:
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(40,20);
ctx.lineTo(100,20);
/*用arcTo函数为当前的子路径添加一条圆弧。5个参数:P1坐标x、P1坐标y、P2坐标x、P2坐标y、圆弧半径*/
ctx.arcTo(120,20,120,40,20);
ctx.lineTo(120,70);
ctx.arcTo(120,90,100,90,20);
ctx.lineTo(40,90);
ctx.arcTo(20,90,20,70,20);
ctx.lineTo(20,40);
ctx.arcTo(20,20,40,20,20);
ctx.stroke();
</script>
1.5 擦除Canvas画板
使用clearRect函数擦除一个矩形区域。他需要4个参数:起点坐标x、坐标y、擦除区域的长和宽。
绘制一个红色实心矩形,再擦除一个5050的小矩形:*
<canvas id="myCanvas" width="200" height="100">
你的浏览器不支持 HTML5
</canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle = "red";
ctx.beginPath();
ctx.fillRect(10,10,200,100);
ctx.clearRect(30,30,50,50);
ctx.stroke();
</script>
二、绘制复杂图形
2.1 画曲线
二次贝塞尔曲线:
二次贝塞尔曲线有一个控制点,再Canvas中用quadraticCurveTo(cpx,cpy,x,y)函数绘制。cpx,cpy表示控制点的坐标,x,y表示终点坐标。
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(100,100);
ctx.quadraticCurveTo(20,50,200,20);
ctx.stroke();
</script>
三次贝塞尔曲线:
二次、三次贝塞尔曲线的区别在于三次的有两个控制点。
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.moveTo(68,130);
var cX1 = 20;
var cY1 = 10;
var cX2 = 268;
var cY2 = 10;
var endX = 268;
var endY = 170;
ctx.bezierCurveTo(cX1,cY1,cX2,cY2,endC,endY);
ctx.stroke();
</script>
2.2 利用clip在指定区域绘图
clip函数使用当前路径作为绘制操作的剪辑区域。可以理解为窗户,不论绘制了多大的图形,最后看到的图像只能由clip这扇窗来决定。
先画圆,使用clip,再画矩形,最后只能看到圆
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.arc(100,100,40,0,360*Math.PI/180,true);
ctx.clip();
ctx.beginPath();
//设定颜色
ctx.fillStyle="lightblue";
//绘制矩形
ctx.fillRect(0,0,300,150);
</script>
2.3 绘制自定义图形
结合各种方法,绘制特殊图形,例如:
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(100, 150);
ctx.bezierCurveTo(50, 100, 100, 0, 150, 50);
ctx.bezierCurveTo(200, 0, 250, 100, 200, 150);
ctx.bezierCurveTo(250, 200, 200, 300, 150, 250);
ctx.bezierCurveTo( 100, 300, 50, 200,100, 150);
ctx.closePath();
ctx.moveTo(100, 150);
ctx.lineTo(150, 50);
ctx.lineTo(200, 150);
ctx.lineTo(150, 250);
ctx.lineTo(100, 150);
ctx.lineWidth = 5;
ctx.strokeStyle = "#ff0000";
ctx.stroke();
</script>
三、绘制文本
3.1 绘制文字
使用fillText绘制实心文字
fillText(text,x,y,max Width)函数,4各参数分别是:文本字符串、坐标x、坐标y、文本宽度。其中文本宽度可以省略,当其省略时,文本宽度会自动定为整个文本的宽度。
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
//设定文字大小和字体
ctx.font="30px Arial";
//描画文字
ctx.fillText("Hello World",100,50);
//或添加文本宽度参数:
//ctx.fillText("Hello World",100,50,50);
</script>
使用strokeText绘制空心文字:
strokeText与fillText用法相同,只是fillText为实心文字,strokeText为空心文字
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
//设定文字大小和字体
ctx.font="30px Arial";
//描画文字
ctx.strokeText("Hello World",100,50);
</script>
3.2 文字设置
3.2.1 文字大小
使用font参数:例如:ctx.font="50px Arial";
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
//设定文字大小为30px
ctx.font="30px Arial";
ctx.fillText("Hello World",100,50);
ctx.beginPath();
//设定文字大小为50px
ctx.font="50px Arial";
ctx.fillText("Hello World",100,150);
ctx.beginPath();
//设定文字大小为100px
ctx.font="70px Arial";
ctx.fillText("Hello World",100,250);
</script>
3.2.2 文字字体
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
//设定文字字体为Arial
ctx.font="30px Arial";
ctx.fillText("Hello World (Arial)",50,50);
ctx.beginPath();
//设定文字字体为Verdana
ctx.font="30px Verdana";
ctx.fillText("Hello World (Verdana)",50,100);
ctx.beginPath();
//设定文字字体为Times New Roman
ctx.font="30px Times New Roman";
ctx.fillText("Hello World (Times New Roman)",50,150);
ctx.beginPath();
//设定文字字体为Courier New
ctx.font="30px Courier New";
ctx.fillText("Hello World (Courier New)",50,200);
ctx.beginPath();
//设定文字字体为serif
ctx.font="30px serif";
ctx.fillText("Hello World (serif)",50,250);
ctx.beginPath();
//设定文字字体为sans-serif
ctx.font="30px sans-serif";
ctx.fillText("Hello World (sans-serif)",50,300);
</script>
3.2.3 文字粗体效果
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
//设定font-weight为normal
ctx.font='normal 30px Arial';
ctx.fillText("Hello World (normal)",50,50);
ctx.beginPath();
//设定font-weight为bold
ctx.font='bold 30px Arial';
ctx.fillText("Hello World (bold)",50,90);
ctx.beginPath();
//设定font-weight为bolder
ctx.font='bolder 30px Arial';
ctx.fillText("Hello World (bolder)",50,130);
ctx.beginPath();
//设定font-weight为lighter
ctx.font='lighter 30px Arial';
ctx.fillText("Hello World (lighter)",50,170);
ctx.beginPath();
//设定font-weight为100
ctx.font='100 30px Arial';
ctx.fillText("Hello World (100)",50,210);
ctx.beginPath();
//设定font-weight为600
ctx.font='600 30px Arial';
ctx.fillText("Hello World (600)",50,250);
ctx.beginPath();
//设定font-weight为900
ctx.font='900 30px Arial';
ctx.fillText("Hello World (900)",50,290);
</script>
3.2.4 文字斜体效果
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
//设定font-weight为normal
ctx.font='normal 30px Arial';
ctx.fillText("Hello World (normal)",50,50);
ctx.beginPath();
//设定font-style为italic
ctx.font='italic 30px Arial';
ctx.fillText("Hello World (italic)",50,90);
ctx.beginPath();
//设定font-style为oblique
ctx.font='oblique 30px Arial';
ctx.fillText("Hello World (oblique)",50,130);
</script>
3.3 文字的对齐效果
3.3.1 水平对齐
</canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.moveTo(160,0);
ctx.lineTo(160,300);
ctx.stroke();
ctx.beginPath();
ctx.textAlign='start';
ctx.font='30px Arial';
ctx.fillText("Hello World",160,50);
ctx.beginPath();
ctx.textAlign='end';
ctx.font='30px Arial';
ctx.fillText("Hello World",160,100);
ctx.beginPath();
ctx.textAlign='left';
ctx.font='30px Arial';
ctx.fillText("Hello World",160,150);
ctx.beginPath();
ctx.textAlign='center';
ctx.font='30px Arial';
ctx.fillText("Hello World",160,200);
ctx.beginPath();
ctx.textAlign='right';
ctx.font='30px Arial';
ctx.fillText("Hello World",160,250);
</script>
3.3.2 竖直对齐
<script type="text/javascript">
var c=document.getElementById('myCanvas');
var ctx=c.getContext('2d');
ctx.textBaseline='alphabetic';
ctx.font='30px Arial';
ctx.fillText('Hello World',50,50);
ctx.moveTo(0,50);
ctx.lineTo(250,50);
ctx.stroke();
ctx.textBaseline='bottom';
ctx.font='30px Arial';
ctx.fillText('Hello World',50,100);
ctx.moveTo(0,100);
ctx.lineTo(250,100);
ctx.stroke();
ctx.textBaseline='hanging';
ctx.font='30px Arial';
ctx.fillText('Hello World',50,150);
ctx.moveTo(0,150);
ctx.lineTo(250,150);
ctx.stroke();
ctx.textBaseline='ideographic';
ctx.font='30px Arial';
ctx.fillText('Hello World',50,200);
ctx.moveTo(0,200);
ctx.lineTo(250,200);
ctx.stroke();
ctx.textBaseline='middle';
ctx.font='30px Arial';
ctx.fillText('Hello World',50,250);
ctx.moveTo(0,250);
ctx.lineTo(250,250);
ctx.stroke();
ctx.textBaseline='top';
ctx.font='30px Arial';
ctx.fillText('Hello World',50,300);
ctx.moveTo(0,300);
ctx.lineTo(250,300);
ctx.stroke();
</script>
<label style="color:orange">四、图片操作
4.1 利用drawImage绘制图片
drawImage函数有3种函数原型,语法如下:
drawImages(image,dx, dy);
drawImages(image,dx, dy, dw, dh);
drawImages(image,sx, sy, sw, sh, dx, dy, dw, dh);
- image是要绘制的对象,可以说HTMLImageRlement、HTML-CanvasElement或者HTMLVideoElement
- dx、dy是image在Canvas中定位的坐标值
- dw、dh表示image在Canvas中即将绘制区域(相对dx、dy坐标的偏移量)的宽度与高度值
- sx、sy是image所要绘制的起始位置
- sw、sh表示image所要绘制区域(相对sw、sy坐标的偏移量)的宽度与高度值
方式1:在Canvas中通过<img>标签的id取得图片数据
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
img标签<br />
<img id="face" src="face.jpg" alt="The Face" width="240" height="240" /><br />
canvas画板<br />
<canvas id="myCanvas" width="500" height="350">
你的浏览器不支持HTML5
</canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById("face");
img.onload = function(){
ctx.drawImage(img,10,10);
};
</script>
</body>
</html>
步骤1:在html中加入<img>标签
<img id="face" src="face.jpg" alt="The Face" width="240" height="240" /><br />
步骤2:在Canvas中通过<img>标签的id取得图片数据
var img=document.getElementById("face");
步骤3:用drawImage函数江图片绘制到画板上
ctx.drawImage(img,10,10);
方式2:在Canvas中通过 JavaScript 的 Image 对象来获取数据(个人推荐这种)
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<canvas id="myCanvas" width="500" height="350">
你的浏览器不支持HTML5
</canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var image = new Image();
image.src = "face.jpg";
image.onload = function(){
ctx.drawImage(image,10,10);
};
</script>
</body>
</html>
步骤1:建立image对象
var image = new Image();
步骤2:通过设置scr属性,载入图片
image.src = "face.jpg";
步骤3:添加onload事件侦听,当图片载入完成时,将其绘制到画板
image.onload = function(){
ctx.drawImage(image,10,10);
};
drawImage函数的3种函数原型的用法与区别:
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var image = new Image();
image.src = "face.jpg";
image.onload = function(){
/*从坐标(10,10)开始绘制整张图片*/
ctx.drawImage(image,10,10);
/*从坐标(260,10)开始绘制整张图片到长100、宽100的矩形区域内*/
ctx.drawImage(image,260,10,100,100);
/*截取图片从(50,50)到(100,100)的部分,从坐标(260,130开始绘制,放大长100,宽100的矩形区域内)*/
ctx.drawImage(image,50,50,100,100,260,130,100,100);
};
</script>
4.2 利用getImageData和putImageData绘制图片(不推荐)
putImageData(imagedata,dx, dy, sx, sy, sw, sh)
- imagedata为像素数据
- dx、dy是绘制图片的定位坐标值
- sx、sy是imagedata所要绘制图片的起始位置
- sw、sh表示imagedata所要绘制区域(相对imagedata的sx、sy坐标的偏移量)的宽度与高度值
这里第四个参数及以后的所有参数都可以省略,如果省略则表示绘制整个imagedata。
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var image = new Image();
image.src = "face.jpg";
image.onload = function(){
ctx.drawImage(image,10,10);
var imgData=ctx.getImageData(50,50,200,200);
ctx.putImageData(imgData,10,260);
ctx.putImageData(imgData,200,260,50,50,100,100);
};
</script>
步骤1:图片数据读取完成后,首先江图片数据绘制到Canvas画板上
ctx.drawImage(image,10,10);
步骤2:用getImageData函数从画板上取得像素数据
var imgData=ctx.getImageData(50,50,200,200);
步骤3:将取得的整个像素数据绘制到画板上
ctx.putImageData(imgData,10,260);
或将取得的整个像素数据的一部分绘制到画板上
ctx.putImageData(imgData,200,260,50,50,100,100);
注意:这种方法种使用了getImageData函数获取图片数据,这个函数在Google Chrome等浏览器中会涉及跨域问题,所以无法直接在浏览器种浏览。必须通过服务器来访问。当然,我么可以在本地服务器是浏览。
4.3 利用createImageData新建像素
createImageData函数有两种函数原型:
- 返回指定大小的imageData对象:
createImageData(sw, sh);
- 返回与指定对象相同大小的imageData对象
createImageData(imageData);
注意:通过createImageData返回的是一个空的imageData对象,必须要针对起像素进行复制才能显示到Canvas 画板上
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var image = new Image();
image.src = "face.jpg";
image.onload = function(){
ctx.drawImage(image,10,10);
var imgData=ctx.getImageData(50,50,200,200);
var imgData01=ctx.createImageData(imgData);
for (i=0; i<imgData01.width*imgData01.height*4;i+=4){
imgData01.data[i+0]=255;
imgData01.data[i+1]=0;
imgData01.data[i+2]=0;
imgData01.data[i+3]=255;
}
ctx.putImageData(imgData01,10,260);
var imgData02=ctx.createImageData(100,100);
for (i=0; i<imgData02.width*imgData02.height*4;i+=4){
imgData02.data[i+0]=255;
imgData02.data[i+1]=0;
imgData02.data[i+2]=0;
imgData02.data[i+3]=155;
}
ctx.putImageData(imgData02,220,260);
};
</script>
代码解析:
-
图片数据读取完成后,首先将图片数据绘制到 Canvas 画板上。
ctx.drawImage(image,10,10);
-
用 getImageData 函数从画板上取得像素数据。
var imgData=ctx.getImageData(50,50,200,200);
-
使用 createImageData 返回与 imgData 相同大小的 ImageData 对象。
var imgData01=ctx.createImageData(imgData);
-
imgData01 进行赋值。
for (i=0; i<imgData01.widthimgData01.height4;i+=4){
imgData01.data[i+0]=255;
imgData01.data[i+1]=0;
imgData01.data[i+2]=0;
imgData01.data[i+3]=255;
} -
利用 putImageData 将 imgData01 画到 Canvas 画板上。
ctx.putImageData(imgData01,10,260);
-
使用 createImageData 返回一个大小为 100×100 的 ImageData 对象。
var imgData02=ctx.createImageData(100,100);
-
对 imgData02 进行赋值。
for (i=0; i<imgData02.widthimgData02.height4;i+=4){
imgData02.data[i+0]=255;
imgData02.data[i+1]=0;
imgData02.data[i+2]=0;
imgData02.data[i+3]=155;
} -
利用 putImageData 将 imgData02 画到 Canvas 画板上。
ctx.putImageData(imgData02,220,260);
五、致谢
写这篇学习总结的时候是学校开学的前夕,实验室还没有人。早上我给自己泡了一杯茶,累了就去弹两首古琴曲子然后继续回来学。这篇总结写完的时候,太阳的余辉正撒在我的书桌上。我抬头望着窗外的云朵,好像忽然懂了《时光恋旅人》里主角父亲穿越时空一遍遍看书的感受了,哈哈哈,在时空隧道里,想来我一个人也可以相处的很愉快吧。
本文内容是我对张路斌老师《HTML5 Canvas 游戏开发实战》第二章的学习总结,感谢张路斌老师,也感谢阅读本文的你给我的鼓励!
也欢迎来我的网页踩踩哦,网页里阅读更轻松~网页入口在这哦
作为一个前端小白,如果学习笔记中有错误的地方,还请不吝指点,谢谢!