canvas
一.什么是canvas:canvas其实就是html5里面的一个新的标签
<canavs></canvas>
1.canvas是一个矩形区域的画布,可以用js在上面绘画,控制其每一个像素
2.canvas标签使用js在网页上绘制图像,本身并不具备绘画功能
3.canvas有多种绘制路径、矩形、圆形、字符以及添加图像的方法
二.canvas语法
1.设置canvas的宽高是通过canvas的属性去设置的,而不是css
<canvas
width="600"
height="600"></canvas>
并且属性值的单位必须是px,否则会忽略
2.width和height默认是300*150px
3.注意:
(1)不要用css控制canvas的宽高,会造成图片拉伸
(2)重新设置canvas标签的宽高属性会让画布擦除所有内容
(3)可以给canvas画布设置背景颜色
三.浏览器不兼容处理
1.ie9以上才支持canvas,其他什么谷歌、火狐、苹果浏览器等都支持
2.只要浏览器兼容canvas,就会支持大部分api
3.移动端的兼容情况非常理想,基本上可以随便使用
4.2d的支持都非常好,3die11才支持,其他浏览器都支持
5.如果浏览器不兼容,最好进行友好提示
6.如果浏览器不兼容,可以使用flash等手段进行优雅降级
四.canvas绘图上下文context
1.context:canvas的上下文、绘制环境
(1)上下文:是所有挥之操作api的入口/集合(其实就是一系列功能的封装体)
(2)canvas自身无法绘制任何内容,它的绘图是使用js操作的
(3)context对象就是js操作canvas的接口。使用[CanvasElement].getContext(‘2d’)来获取2D绘图上下文
---->var canvas
= document.getElementById( 'cavsElem' ); //获得画布
var ctx = canvas.getContext( '2d' );//注意:2d小写,
3d:webgl
(4)获取上下文通过js:要在canvas上绘制内容就必须要等到canvas加载完成,所以<script></script>要卸载</cnavas>之后
五.基本绘制路径
1.canvas坐标系:从最左上角(0,0)开始,x向右增大,y向下增大
2.设置绘制起点(moveTo)
(1)语法:ctx.moveTo(x,y)
(2)解释:设置上下文绘制路径的起点,相当于移动画笔到某个位置
(3)参数:x,y都是相对于canvas盒子的最左上角
(4)注意:绘制线段前必须先设置起点,不然绘制无效
3.绘制直线(lineTo)
(1)语法:ctx.lineTo(x,y)
(2)解释:从x,y的位置绘制一条直线到起点/上一个线头点
(3)参数:(x,y)线头点坐标
2.设置绘制起点(moveTo)
(1)语法:ctx.moveTo(x,y)
(2)解释:设置上下文绘制路径的起点,相当于移动画笔到某个位置
(3)参数:x,y都是相对于canvas盒子的最左上角
(4)注意:绘制线段前必须先设置起点,不然绘制无效
3.绘制直线(lineTo)
(1)语法:ctx.lineTo(x,y)
(2)解释:从x,y的位置绘制一条直线到起点/上一个线头点
(3)参数:(x,y)线头点坐标
4.路径开始和闭合
(1)开始路径:ctx.beginPath();
核心的作用是将不同绘制的形状进行隔离。每次执行此方法都表示重新绘制一个路径,和之前绘制的墨迹可以进行分开样式设置和管理(其实就是开一个新路径,开启新状态的绘图,新状态可以继承之前状态的样式,但是当前状态设置的所有样式只能作用于当前的状态)
(2)闭合路径:ctx.closePath();
(3)解释:复杂的路径绘制必须使用路径开始和结束。闭合路径会自动把最后的线头和开始的线头连在一起
5.描边(stroke)
(1)语法:ctx.stroke();
(2)解释:根据路径绘制线。路径只是草稿,真正绘制线必须使用stroke
(3)ctx.strokeStyle = “颜色”; 控制描边的颜色
(4)设置线宽:ctx.lineWidth = 数字;
6.填充(fill)
(1)语法:ctx.fill();
(2)解释:将闭合路径的内容填充具体的颜色,默认是黑色。如果需要设置别的颜色就要用ctx.fillStyle = '颜色';
(3)注意:交叉路径的填充问题——“非零环绕原则”,顺逆时针穿插次数决定是否填充
以下是非0环绕原则的原理:(了解即可,非常少会用到复杂的路径)
“非零环绕规则”是这么来判断有自我交叉情况的路径的:对于路径中的任意给定区域,从该区域内部画一条足够长的线段,
使此线段的终点完全落在路径范围之外。
图2-14中的那三个箭头所描述的就是上面这个步骤。
接下来,将计数器初始化为0,
然后,每当这条线段与路径上的直线或曲线相交时,
就改变计数器的值。如果是与路径的顺时针部分相交,则加1,
如果是与路径的逆时针部分相交,则减1。若计数器的最终值不是0,那么此区域就在路径里面,在调用fill()方法时,
浏览器就会对其进行填充。
如果最终值是0,那么此区域就不在路径内部,浏览器也就不会对其进行填充了
7.canvas绘制的基本步骤
(1)获得上下文 => canvasElem.getContext('2d');
(2)开始路径规划 => ctx.beginPath()
(3)移动起始点 => ctx.moveTo(x, y)
(4)绘制线 => ctx.lineTo(x, y)
(5)闭合路径 => ctx.closePath()
(6)绘制描边 => ctx.stroke();
<!DOCTYPE
html>
<html
lang="en">
<head>
<meta
charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
<!--设置canvas标签的宽高是通过canvas标签的属性设置的,而不是用css-->
<canvas
id="demo"
width="600"
height="600"></canvas>
<script>
window.onload =
function(){
//第一步:拿到canvas标签
var
canvas =
document.getElementById('demo');
canvas.style.border
=
"1px solid red";
//第二部:拿到canvas的上下文
var
ctx = canvas.getContext('2d');
//第三部:开始绘制
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.lineTo(100,200);
// ctx.lineTo(100,100);
ctx.closePath();
//上面这些只是将画笔移动到特定的位置,下面的代码才是有线显示
ctx.stroke();
}
</script>
</body>
</html>
8.canvas是基于状态的绘图
六.绘制矩阵(rect)
1.快速创建矩形rect()方法
(1)语法:ctx.rect(x,y,width,height);
(2)解释:x,y是矩形左上角坐标,width和height都是以像素计
(3)注意
·rect方法只是规划了矩形的路径,并没有填充和描边
2.快速创建描边矩形和填充矩形
(1)语法:ctx.strokeRect(x,y,width,height);此方法绘制万路径之后立即进行stroke绘制
ctx.fillRect(x,y,width,height); 此方法绘制完路径之后立即对当前矩阵进行fill填充
(2)解释:x,y是矩形左上角坐标,width和height都是以像素计
3.清除矩阵
(1)语法:ctx.clearRect(x,y,width,height);
(2)解释:清除某个矩阵内绘制的内容,相当于橡皮擦
七.绘制圆形(arc):arc()方法创建弧/曲线(用于创建圆/部分圆)
1.语法:ctx.arc(x,y,r,sAngle,eAngle,counterclockwise);
2.解释:
·x,y:圆心坐标
·r:半径大小
·sAngle:绘制开始的角度(起始点和0度坐标线的夹角),圆心到最右边点是0度,顺时针方向弧度增大(注意和我们通常的坐标系有区别)
·eAngle:结束的角度(结束点和0度坐标线的夹角),注意是弧度。π
·counterclockwise:是否是逆时针。ttrue是逆时针false是顺时针
·弧度和角度的转化公式:rad = deg*Math.PI/180;
·在Math提供的方法中sin、cos等都使用的弧度
八.绘制文字(会使用就可以了)
1.绘制空心的文字:ctx.strokeText(“要绘制的文字”,文字的x坐标,文字的y坐标)
2.绘制实心的文字:ctx.fillText(“要绘制的文字”,文字的x坐标,文字的y坐标)
九.绘制上下文的文字属性(有印象就可以了)
1.font:设置/返回文本内容的当前字体属性
(1)font属性使用的语法与CSS font属性相同
例如:ctx.font = "18px '微软雅黑'";
(2)textAlign:设置/返回文本内容的当前对齐方式
·start:默认。文本在指定的位置开始
·end:文本在指定的位置结束
·center:文本的中心被放置在指定的位置
·left:文本左对齐
·right:文本右对齐
*
例如:ctx.textAlign = 'left';
行高:两行文本基线的距离
(3)textBaseline:设置/返回在绘制文本时使用的当前文本基线
·alphabetic:默认。文本基线是普通的字母基线
·top:文本基线是em方框的顶端
·hanging:文本基线是悬挂基线
·middle:文本基线是em方框的正中
·ideographic:文本基线是em基线
·bottom:文本基线是em方框的底端
十.上下文绘制文字方法
1.ctx.fillText():在画布上绘制“被填充的文本”
2.ctx.strokeText():在画布上绘制空心文本(无填充)
3.ctx.measureText():返回包含指定文本宽度的对象(测量文本的宽度,在()里面放置文本的话就会自动返回文本的宽度)
ctx.moveTo( 300, 300 );
ctx.fillStyle = "purple";
//设置填充颜色为紫色
ctx.font = '20px "微软雅黑"';
//设置字体
ctx.textBaseline = "bottom";
//设置字体底线对齐绘制基线
ctx.textAlign = "left";
//设置字体对齐的方式
//ctx.strokeText( "left", 450, 400 );
ctx.fillText( "Top-g", 100, 300 );
//填充文字
十一.绘制图片
1.基本绘制图片的方式:context.drawImage(img,x,y);
(1)解释:x,y绘制图片左上角的坐标,img绘制图片的dom对象
2.在画布上绘制图像并规定图像的宽高:context.drawImage(img,x,y,width,height)
(1)解释:width绘制图片的宽度,height绘制图片的高度
(2)注意:如果指定宽高,最好成比例,否则图片会被拉伸
·等比公式:toH = Height * toW / width
设置高 = 原高度 * 设置宽 / 原宽度
3.图片剪裁并在画布上定位被剪切的部分:context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height)
(1)解释:sx、sy —— 剪裁图片的左上角坐标
swidth —— 剪裁图片的宽度(将要截取的图片的宽)
sheight —— 剪裁图片的高度
x,y ——
将要绘制到画布的哪里(绘制图片左上角的坐标)
4.用js创建img对象
(1)var img = document.getElementById(“imgId”);
(2)var img = new Image() ; //这个就是img标签的dom对象
img.src = “”; //只要设置了src,当前的img对象就会立即去加载图片
img.alt = “”;
img.onload = function(){
//图片加载完成后执行该方法(图片加载完成之后再绘制到canvas上)
}
<!DOCTYPE
html>
<html
lang="en">
<head>
<meta
charset="UTF-8">
<title></title>
</head>
<body>
<div
id="container">
<canvas
id="cavsElem">
你的浏览器不支持canvas,请升级浏览器
</canvas>
</div>
<script>
(function(){
var
canvas =
document.querySelector(
'#cavsElem'
);
var
ctx = canvas.getContext(
'2d'
);
canvas.width
= 900;
canvas.height
= 900;
canvas.style.border
= "1px solid #000";
//第一步:创建图片的dom对象
var
img =
new Image();
img.src
= 'images/a.jpg';
//只要设置了src属性,当前img对象立即去加载图片
img.onload
=
function(){
//图片加载完成之后再绘制到canvas上
ctx.drawImage(img,100,100);
//绘制10条狗
for(var
i =
0 ;
i < 10
; i++){
ctx.drawImage(img,100
+
20 * i,100
+
20 * i);
}
}
}());
</script>
</body>
</html>
结果:
实现虚拟列帧:
<!DOCTYPE
html>
<html
lang="en">
<head>
<meta
charset="UTF-8">
<title></title>
</head>
<body>
<div
id="container">
<canvas
id="cavsElem">
你的浏览器不支持canvas,请升级浏览器
</canvas>
</div>
<script>
(function(){
var
canvas =
document.querySelector(
'#cavsElem'
);
var
ctx = canvas.getContext(
'2d'
);
canvas.width
= 900;
canvas.height
= 900;
canvas.style.border
= "1px solid #000";
//第一步:创建图片的dom对象
var
img =
new Image();
img.src
= 'images/gameImgs/DMMban.png';
//只要设置了src属性,当前img对象立即去加载图片
img.onload
=
function(){
var
frameIndex =
0;
setInterval(function(){
ctx.clearRect(0,0,canvas.width,canvas.height);
//清除之前绘制的图片
// canvas.width = canvas.width; 如果通过代码重新设置canvas画布的宽高,canvas画布里面所有的内容都会被清空,不建议使用这种方法
ctx.drawImage(img,frameIndex
* 40,0,40,65,200,200,80,130);
//绘制图片
frameIndex ++;
//绘制完图片后让帧++,添加到下一帧
frameIndex %=
4;
//取余数
},1000/10);
//10帧:100ms绘制一次图片
}
}());
</script>
</body>
</html>
十二.设置阴影(了解,较少用,性能很差)
- 类比于CSS3的阴影。
- shadowColor : 设置或返回用于阴影的颜色
- shadowBlur : 设置或返回用于阴影的模糊级别,大于1的正整数,数值越高,模糊程度越大
- shadowOffsetX: 设置或返回阴影距形状的水平距离
- shadowOffsetY: 设置或返回阴影距形状的垂直距离
ctx.fillStyle = "rgba(255,0,0, .9)"
ctx.shadowColor = "teal";
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
ctx.fillRect(100, 100, 100, 100);
十三.复杂样式
1.创建线性渐变样式(了解)
- 一般不用,都是用图片代替,canvas绘制图片效率更高。
- 线性渐变可以用于 矩形、圆形、文字等颜色样式
- 线性渐变是一个对象
- 语法:ctx.createLinearGradient(x0,y0,x1,y1); //参数:x0,y0起始坐标,x1,y1结束坐标
例如:
//创建线性渐变的对象,
var grd=ctx.createLinearGradient(0,0,170,0);
grd.addColorStop(0,"black");
//添加一个渐变颜色,第一个参数介于
0.0
与
1.0
之间的值,表示渐变中开始与结束之间的位置。
grd.addColorStop(1,"white");
//添加一个渐变颜色
ctx.fillStyle =grd;
//关键点,把渐变设置到
填充的样式
2.设置圆形渐变(径向渐变,了解)
- 创建放射状/圆形渐变对象。可以填充文本、形状等
- context.createRadialGradient(x0,y0,r0,x1,y1,r1);
- radial 半径的;放射状的;光线的;光线状的 英 ['reɪdɪəl] 美 ['redɪəl]
-
参数详解:
- x0: 渐变的开始圆的 x 坐标
- y0: 渐变的开始圆的 y 坐标
- r0: 开始圆的半径
- x1: 渐变的结束圆的 x 坐标
- y1: 渐变的结束圆的 y 坐标
- r1: 结束圆的半径
var rlg = ctx.createRadialGradient(300,300,10,300,300,200);
rlg.addColorStop(0, 'teal');
//添加一个渐变颜色
rlg.addColorStop(.4, 'navy');
rlg.addColorStop(1, 'purple');
ctx.fillStyle = rlg;//设置
填充样式为延续渐变的样式
ctx.fillRect(100, 100, 500, 500);
3.绘制背景图(了解)
- ctx.createPattern(img,repeat) 方法在指定的方向内重复指定的元素了解
- pattern:n. 模式;图案;样品 英 ['pæt(ə)n] 美 ['pætɚn]
-
第一参数:设置平铺背景的图片,第二个背景平铺的方式。
- image : 规定要使用的图片、画布或视频元素。
- repeat : 默认。该模式在水平和垂直方向重复。
- repeat-x : 该模式只在水平方向重复。
- repeat-y : 该模式只在垂直方向重复。
- no-repeat: 该模式只显示一次(不重复)。
var ctx=c.getContext("2d");
var img=document.getElementById("lamp");
var pat=ctx.createPattern(img,"repeat");
ctx.rect(0,0,150,100);
ctx.fillStyle=pat;//
把背景图设置给填充的样式
ctx.fill();
十四.变换(重点)
1.缩放(重点):scale() —— 缩放当前绘图,更大/更小
(1)语法:context.scale(scaleWidth,scaleHeight)
(2)参数解释
·scaleWidth:缩放当前绘图的宽度(1=100%,0.5=50%,2=200%)
·scaleHeight:缩放当前绘图的高度
(3)注意:缩放的是整个画布,缩放后继续绘制的图形会被放大/缩小
2.位移画布(重点):ctx.translate(x,y) —— 重新映射画布上(0,0)的位置
(1)参数解释:
·x:添加到水平坐标(x)上的值
·y:添加到垂直坐标(y)上的值
(2)发生位移后相当于把画布的(0,0)坐标更换到(x,y)的位置,所有绘制的新元素都会被影响
(3)位移画布一般配合缩放和旋转等
3.旋转(重点):context.rotate(angle):方法旋转当前的绘图
(1)注意参数的单位是弧度
(2)如果需要将角度转化为弧度就使用degrees*Math.PI/180
公式进行计算
4.绘制环境保存和还原(重要)
(1)ctx.save():保存当前环境的状态(把当前上下文的状态保存起来,可以把当前绘制环境进行保存到缓存中)
(2)ctx.restore():返回之前保存过的路径状态和属性(把之前保存的上下文再挪出来,获取最近缓存的ctx)
(3)一般配合位移画布使用
5.设置绘制环境的透明度(了解)
- context.globalAlpha=number;
- number:透明值。必须介于 0.0(完全透明) 与 1.0(不透明) 之间。
- 设置透明度是全局的透明度的样式。注意是全局的。
6.画布限定区域绘制(了解)
- ctx.clip(); 方法从原始画布中剪切任意形状和尺寸
- 一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)
- 一般配合绘制环境的保存和还原。
7.画布保存base64编码内容(重要):把canvas绘制的内容输出成base64内容
(1)语法:canvas.toDataURL(type,encoderOptions)
(2)参数说明:
·type设置输出的类型(比如image/png image/jpeg等)
·encoderOptions:0-1之间的数字,用于标识输出图片的质量,1表示无损压缩,类型为image/jpeg或image/webp才能起作用
8.画布渲染画布(重点):context.drawimage(img,x,y);
(1)参数说明:img参数也可以是画布,也就是把画布整体渲染到另一个画布上
9.线条样式(了解)
-
lineCap
设置或返回线条的结束端点(线头、线冒)样式
-
butt
: 默认。向线条的每个末端添加平直的边缘。
- 翻译.:屁股;烟头;笑柄;靶垛;粗大的一端 英 [bʌt] 美 [bʌt]
- round : 向线条的每个末端添加圆形线帽。
-
butt
: 默认。向线条的每个末端添加平直的边缘。
square:
向线条的每个末端添加正方形线帽。
-
lineJoin
设置或返回两条线相交时,所创建的拐角类型
-
bevel:
创建斜角。
- 翻译. 斜角;斜面;[测] 斜角规 英 ['bev(ə)l] 美 ['bɛvl]
- round: 创建圆角。
- miter: 默认。创建尖角
-
bevel:
创建斜角。
- lineWidth 设置或返回当前的线条宽度
-
miterLimit
设置或返回最大斜接长度
- 意思: 斜接 英 ['maɪtə]
- 斜接长度指的是在两条线交汇处内角和外角之间的距离。
-
一般用默认值:10就可以了。除非需要特别长的尖角时,使用此属性。
十五.了解贝塞尔曲线
1.绘制一条二次方曲线(知道有就行了)
- 微软的画图板中的曲线的颜色。
- quadratic:二次方的意思, 英 [kwɒ'drætɪk] 美 [kwɑ'drætɪk]
- Curve:曲线的意思, 英 [kɜːv] 美 [kɝv]
- 语法: context.quadraticCurveTo(cpx,cpy,x,y);
-
参数:
- cpx: 贝塞尔控制点的 x 坐标
- cpy: 贝塞尔控制点的 y 坐标
- x : 结束点的 x 坐标
y
:
结束点的
y
坐标
2.绘制贝塞尔曲线(知道有就行)
- 绘制一条三次贝塞尔曲线
- 语法:context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
- 提示:三次贝塞尔曲线需要三个点。前两个点是用于三次贝塞尔计算中的控制点,第三个点是曲线的结束点。曲线的开始点是当前路径中最后一个点。如果路径不存在,那么请使用 beginPath() 和 moveTo() 方法来定义开始点。
-
参数说明:
- cp1x: 第一个贝塞尔控制点的 x 坐标
- cp1y: 第一个贝塞尔控制点的 y 坐标
- cp2x: 第二个贝塞尔控制点的 x 坐标
- cp2y: 第二个贝塞尔控制点的 y 坐标
- x: 结束点的 x 坐标
- y: 结束点的 y 坐标
//绘制复杂的贝塞尔曲线
ctx.beginPath();
ctx.moveTo(400,400);
//参数说明:context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
// cp1x:
第一个贝塞尔控制点的
x
坐标
// cp1y:
第一个贝塞尔控制点的
y
坐标
// cp2x:
第二个贝塞尔控制点的
x
坐标
// cp2y:
第二个贝塞尔控制点的
y
坐标
// x:
结束点的
x
坐标
// y:
结束点的
y
坐标
ctx.bezierCurveTo(500, 200, 600, 600, 700, 300);
ctx.stroke();
3.创建两条切线的弧(知道有就行)
- 在画布上创建介于当前起点和两个点形成的夹角的切线之间的弧
- 语法: context.arcTo(x1,y1,x2,y2,r); //类比:css3中的圆角。
- 例如: ctx.arcTo(240, 100, 240, 110, 40);
-
参数:
- x1: 弧的端点1的 x 坐标
- y1: 弧的端点1的 y 坐标
- x2: 弧的端点2(终点)的 x 坐标
- y2: 弧的端点2(终点)的 y 坐标
- r : 弧的半径
//代码demo:
ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(200,100);
//context.arcTo(x1,y1,x2,y2,r); //类比:css3中的圆角。
ctx.arcTo(240, 100, 240, 110, 40);
ctx.lineTo(240, 300);
ctx.stroke();
4.了解断点是否在路径中(知道有就行)
context.isPointInPath(x,y);
//isPointInPath()
方法返回
true,如果指定的点位于当前路径中;否则返回
false。
//判断x,y坐标的点是否在当前的路径中。
5.了解文本宽度的计算(知道有就行)
context.measureText(text).width;