简介:
<canvas>
是一个可以使用脚本(通常为JavaScript)在其中绘制图形的 HTML 元素.它可以用于制作照片集或者制作简单(也不是那么简单)的动画. 右边的图片展示了一些 <canvas>
的应用,在这个教程后面我们将看到.
使用 <canvas>
元素不是非常难但你需要一些基本的HTML和JavaScript知识。<canvas>
元素不被一些老的浏览器所支持,但是所有的主流浏览器的新近版本都支持。Canvas 的默认大小为300像素×150像素(宽×高,像素的单位是px)。但是,可以使用HTML的高度和宽度属性来自定义Canvas 的尺寸。为了在 Canvas 上绘制图形,我们使用一个JavaScript上下文对象,它能动态创建图像.
基本语法:
<canvas>元素
<canvas id="c" width="200" height="100"></canvas>
<canvas>
看起来和 <img>
元素很相像,唯一的不同就是它并没有 src 和 alt 属性。实际上,<canvas>
标签只有两个属性—— width
和height
。这些都是可选的,并且同样利用 DOM properties 来设置。当没有设置宽度和高度的时候,canvas会初始化宽度为300像素和高度为150像素。该元素可以使用CSS来定义大小,但在绘制时图像会伸缩以适应它的框架尺寸:如果CSS的尺寸与初始画布的比例不一致,它会出现扭曲。
id
属性并不是<canvas>元素所特有的而是每一个HTML元素(比如class元素)都默认具有的属性。给每个标签都加上一个id属性是个好主意,因为这样你就能在我们的脚本中很容易的找到它。
<canvas>元素可以像任何一个普通的图像一样(有margin
,border
,background
等等属性)被设计。这些样式,然而,不会影响在canvas中的实际图像。我们将会在以后里看到这是如何解决的。当开始时没有为canvas规定样式规则,其将会完全透明。
替换内容
<canvas>元素不同于在其中的<img>
标签,就像<video>
,<audio>
,或者 <picture>
元素一样,很容易定义一些替代内容。由于某些较老的浏览器(尤其是IE9之前的IE浏览器)或者文本浏览器不支持HTML元素"canvas",在这些浏览器上你应该总是能展示替代内容。
这非常简单:我们只是在<canvas>标签中提供了替换内容。支持<canvas>的浏览器将会忽略在容器中包含的内容,并且只是正常渲染canvas.
我们可以提供对canvas内容的文字描述或者是提供动态生成内容相对应的静态图片,如下所示:
<canvas id="c" width="200" height="100">
<span>如果浏览器不支持,显示该文字</span>
</canvas>
<canvas id="c2" width="200" height="100">
<img src="images/bg.jpg" width="200" height="100" alt="背景" />
</canvas>
渲染上下文
<canvas>
元素创造了一个固定大小的画布,它公开了一个或多个渲染上下文,其可以用来绘制和处理要展示的内容。我们将会将注意力放在2D渲染上下文中。其他种类的上下文也许提供了不同种类的渲染方式;比如, WebGL 使用了基于OpenGL ES的3D上下文 ("experimental-webgl") 。
canvas起初是空白的。为了展示,首先脚本需要找到渲染上下文,然后在它的上面绘制。<canvas>
元素有一个 getContext()
的方法,这个方法是用来
获得渲染上下文和它的绘画功能。getContext()
只有一个参数,上下文的格式。对于2D图像而言,如本教程,你可以使用 CanvasRenderingContext2D
。
var oCanvas1 = document.getElementById('c1');
var oCtxt = oCanvas1.getContext('2d');
代码的第一行通过使用
document.getElementById()
方法来为
<canvas>
元素得到DOM对象。一旦有了元素对象,你可以通过使用它的getContext() 方法来访问绘画上下文
检查支持性
通过简单的测试getContext()方法的存在,来检查浏览器是否支持canvas
var oCanvas1 = document.getElementById('c1');
//判断浏览器是否支持
if(oCanvas1.getContext){
var oCtxt = oCanvas1.getContext('2d');
console.log('支持')
}else{
//报错浏览器不支持
}
绘制矩形:
fillRect(x, y, width, height) :绘制一个填充的矩形
strokeRect(x, y, width, height) :绘制一个矩形的边框
clearRect(x, y, width, height) :清除指定矩形区域,让清除部分完全透明
x : 代表 left 值
y :代表的 top 值
width: 代表的是宽
height : 代表的是高
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<style type="text/css">
body{margin:0;background:#000;}
#c1{
background:red;
}
</style>
<script type="text/javascript">
window.οnlοad=function(){
var oC = document.getElementById('c1');
var oCtx = oC.getContext('2d');
oCtx.fillRect(20,20,100,100); //默认填充为黑色
oCtx.clearRect(30,30,50,50); //清除一个矩形,让清除部分完全透明
oCtx.strokeRect(20,140,50,50); //绘制一个边框矩形
}
</script>
</head>
<body>
<canvas id="c1" width="400" height="400"></canvas>
</body>
</html>
关于解决strokeRect() 出现的2像素边框:
oCtx.strokeRect(20,140,50,50); //绘制一个边框矩形,但默认是2像素
oCtx.strokeRect(20.5,200.5,50,50); //向左上各加0.5像素来解决
绘制路径:
图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形需要一些额外的步骤。
- 首先,你需要创建路径起始点。
- 然后你使用画图命令去画出路径。
- 之后你把路径封闭。
- 一旦路径生成,你就能通过描边或填充路径区域来渲染图形。
以下是所要用到的函数:
- 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。
- 闭合路径之后图形绘制命令又重新指向到上下文中。
- 通过线条来绘制图形轮廓。
- 通过填充路径的内容区域生成实心的图形。
- 将笔尖移动到指定的坐标x以及y上
beginPath()
closePath()
stroke()
fill()
moveTo(x,y)
生成路径的第一步叫做beginPath()。本质上,路径是由很多子路径构成,这些子路径都是在一个列表中,所有的子路径(线、弧形、等等)构成图形。而每次这个方法调用之后,列表清空重置,然后我们就可以重新绘制新的图形。
注意:当前路径为空,即调用beginPath()之后,或者canvas刚建的时候,第一条路径构造命令通常被视为是moveTo(),无论最后的是什么。出于这个原因,你几乎总是要在设置路径之后专门指定你的起始位置
第二步就是调用函数指定绘制路径,本文稍后我们就能看到了。
第三,就是闭合路径closePath(),不是必需的。这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做
注意:当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合
Demo:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body{
margin:0;
background:#000;
}
#c{
background:#fff;
}
</style>
</head>
<body>
<canvas id="c" width="400" height="400"></canvas>
<script type="text/javascript">
window.οnlοad=function(){
var oC = document.getElementById('c');
if(oC.getContext){
var oCtx = oC.getContext('2d');
oCtx.beginPath();
oCtx.moveTo(10,10);
oCtx.lineTo(100,10);
oCtx.lineTo(100,60);
oCtx.fill();
}
}
</script>
</body>
</html>
线
绘制直线,需要用到的方法lineTo()
。
- 绘制一条从当前位置到指定x以及y位置的直线。
lineTo(x, y)
moveTo()
函数改变
var oC = document.getElementById('c');
if(oC.getContext){
var oCtx = oC.getContext('2d');
//填充三角形
oCtx.beginPath();
oCtx.moveTo(10,10);
oCtx.lineTo(100,10);
oCtx.lineTo(100,60);
oCtx.fill();
//描边三角形
oCtx.beginPath();
oCtx.moveTo(10,100);
oCtx.lineTo(100,100);
oCtx.lineTo(10,50)
oCtx.closePath();
oCtx.stroke();
}
圆弧:
绘制圆弧或者圆,我们使用arc()
方法。当然可以使用arcTo()
,不过这个的实现并不是那么的可靠,所以我们这里不作介绍。
- 画一个以 (x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。
- 根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。
arc(x, y, radius, startAngle, endAngle, anticlockwise)
arcTo(x1, y1, x2, y2, radius)
这里详细介绍一下arc方法,该方法有六个参数:x,y
为绘制圆弧所在圆上的圆心坐标。radius
为半径。startAngle
以及endAngle
参数用弧度定义了开始以及结束的弧度。这些都是以x轴为基准。参数anticlockwise
为一个布尔值。为true时,是逆时针方向,否则顺时针方向
注意:arc()
函数中的角度单位是弧度,不是度数。角度与弧度的js表达式:radians=(Math.PI/180)*degrees
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body{
margin:0;
background:#000;
}
#c{
background:#fff;
}
</style>
</head>
<body>
<canvas id="c" width="300" height="200"></canvas>
<script type="text/javascript">
window.οnlοad=function(){
var oC = document.getElementById('c');
if(oC.getContext){
var oCtx = oC.getContext('2d');
oCtx.beginPath();
oCtx.arc(75,75,50,0,Math.PI*2,true);//绘制一个外层圆
oCtx.moveTo(105,75);
oCtx.arc(75,75,30,0,Math.PI,false); //绘制口形(逆时针)
oCtx.moveTo(60,60);
oCtx.arc(60,55,5,0,Math.PI*2,true); //右眼
oCtx.moveTo(95,60);
oCtx.arc(90,55,5,0,Math.PI*2,true); //左眼
oCtx.stroke();
}
}
</script>
</body>
</html>
贝塞尔(bezier)以及二次贝塞尔
下一个十分有用的路径类型就是 贝塞尔曲线。一次以及二次贝塞尔曲线都十分有用,一般用来绘制复杂有规律的图形。
-
绘制贝塞尔曲线,
cp1x,cp1y
为控制点,x,y
为结束点。 -
绘制二次贝塞尔曲线,
cp1x,cp1y
为控制点一,cp2x,cp2y
为控制点二,x,y
为结束点
quadraticCurveTo(cp1x, cp1y, x, y)
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style>
body{
margin: 0;
background: #000;
}
#c{
background: #fff;
}
</style>
</head>
<body>
<canvas id="c" width="300" height="200"></canvas>
<script>
/*
* quadraticCurveTo(cp1x, cp1y, x, y),cp1x - cply:起始点x,y坐标,x,y结束点的x,y坐标
* */
window.οnlοad=function(){
var oC = document.getElementById('c');
if(oC.getContext){
var oCtx = oC.getContext('2d');
//绘制贝塞尔曲线
oCtx.beginPath();
oCtx.moveTo(75,25); //==>改变的是下面贝塞尔起点的x,y坐标
oCtx.quadraticCurveTo(25,25,25,64);
oCtx.quadraticCurveTo(25,100,50,100);
oCtx.quadraticCurveTo(50,120,30,125);
oCtx.quadraticCurveTo(60,120,65,100);
oCtx.quadraticCurveTo(125,100,125,62.5);
oCtx.quadraticCurveTo(125,25,75,25);
oCtx.stroke();
}
}
</script>
</body>
</html>
色彩 Colors
到目前为止,我们只看到过绘制内容的方法。如果我们想要给图形上色,有两个重要的属性可以做到:fillStyle
和 strokeStyle。
- 设置图形的填充颜色。
- 设置图形轮廓的颜色。
fillStyle = color
strokeStyle = color
color
可以是表示 CSS 颜色值的字符串,渐变对象或者图案对象。我们迟些再回头探讨渐变和图案对象。默认情况下,线条和填充颜色都是黑色(CSS 颜色值 #000000
)
oCtx.fillStyle="red"; //填充一个背景颜色
oCtx.fillRect(20,20,100,100); //x,y,width,height绘制了一个矩形
oCtx.strokeStyle="black"; //填充一个边框轮廓
oCtx.strokeRect(20,20,100,100);
线型 Line styles
可以通过一系列属性来设置线的样式。
- 设置线条宽度。
- 设置线条末端样式。
- 设定线条与线条间接合处的样式。
- 限制当两条线相交时交接处最大长度 ; 所谓交接处长度 ( 斜接长度 ) 是指线条交接处内角顶点到外角顶点的长度 。
lineWidth = value
lineCap = type
lineJoin = type
miterLimit = value
- 返回一个包含当前虚线样式,长度为非负 偶数的数组。
- 设置当前虚线样式。
- 设置虚线样式的起始偏移量。
getLineDash()
setLineDash(segments)
lineDashOffset = value
通过以下的样例可能会更加容易理解。
lineWidth
属性的例子
这个属性设置当前绘线的粗细。属性值必须为正数。默认值是1.0。
线宽是指给定路径的中心到两边的粗细。换句话说就是在路径的两边各绘制线宽的一半。因为画布的坐标并不和像素直接对应,当需要获得精确的水平或垂直线的时候要特别注意。
在下面的例子中,用递增的宽度绘制了10条直线。最左边的线宽1.0单位。并且,最左边的以及所有宽度为奇数的线并不能精确呈现,这就是因为路径的定位问题