一边看慕课一边整理的文档,刚剥橙子剥到指甲都染色,吃饱了就想睡一会......嗯下面开始写写我都学了点啥
据说是H5中最令人激动的技术,定义在浏览器中的画布,不仅是一个普通的标签,更是一套编程工具、一个编程接口,它的出现依然超过了web基于文档的设定。下面是一些基础的canvas知识。
一、创建canvas
canvas标签直接写在body中即可,当不指定画布大小时,canvas默认300宽150高。指定canvas大小时通常调用属性width和height,css指定的是canvas画布显示大小,属性指定的是分辨率的大小采用这种方式符合c3标准。
<body>
<canvas id="canvas" class="Canvas" width="1024" height="768">当前浏览器不支持canvas,请更换浏览器</canvas>
</body>
也可以在JavaScript中定义canvas的大小,当然js中的优先级比直接在标签中定义的高。
canvas.width =800; //可以在JavaScript中定义canvas的大小,优先级更高
canvas.height =800;
不是所有的浏览器都可以支持canvas,所以当canvas无法显示是,我们需要给用户一些提示,如上图直接在canvas标签中写“当前浏览器不支持canvas,请更换浏览器”即可,当浏览器可以显示canvas时,这句话就不会出现了。
还有一种方式就是写在javascript中,就像下面这样:
//判断浏览器是否支持canvas
if (canvas.getContext("2d")) {
var context = canvas.getCantext("2d")
}
else{
alert("当前浏览器不支持canvas,请更换浏览器")
}
建立了canvas之后如何具体绘制就需要用到javascript:
初始化只有两步
1.首先通过getElementById的方式将刚刚建立的canvas拿出来存放在canvas变量中
2.调用canvas中getContext的方法,传入参数。前期都使用2d绘图。
window.onload = function(){
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
}
二、绘制直线、多边形、七巧板
1.怎么画一条直线?
从坐标100,100到700,700(这个坐标canvas左上角为0,0)
context.moveTo(100,100) //状态设置,表示意愿
context.lineTo(700,700)
context.stroke()
调用moveTo和lineto 两个方法,这两行代码只代表绘图的意愿,状态设置。下面调用stroke才是绘图的过程
2.封闭图形还想上色
context.moveTo(100,100) //状态设置,表示意愿
context.lineTo(700,700)
context.lineTo(100,700)
context.lineTo(100,100)
//颜色填充
context.fillStyle="yellow"
context.fill()
context.lineWidth = 10
context.strokeStyle = "pink"
context.stroke()
一直lineTo回到原点就可以完成封闭图形的绘制,调用lineWidth和strokeStyle两个属性可以设置线条粗细和颜色,这个颜色写在字符串里可以使十六进制数也可以用rgb();
调用fillStyle属性可以添加颜色,但要注意context.fill()才是完成上色的动作步骤。
3.还想画两个
//绘制三角形
context.moveTo(100,100) //状态设置,表示意愿
context.lineTo(700,700)
context.lineTo(100,700)
context.lineTo(100,100)
//颜色填充
context.fillStyle="yellow"
context.fill()
context.lineWidth = 10
context.strokeStyle = "pink"
context.stroke()
//绘制直线
context.beginPath()
context.moveTo(200,100)
context.lineTo(700,600)
context.closePath()
context.lineWidth=2
context.strokeStyle="blue"
context.stroke()
这样就完成了一个三角形和一条直线的绘制,就长这样:
从图中可以看出有两个三角形边,因为一共写了两个context.stroke()函数,下面的函数在执行时连同上面的三角形也绘制一遍。这就对线条上色产生困扰,怎么使是两个图形独立呢?就又要用到context.beginPath()和context.closePath(),如下图写在在图形开始和结束时,所有的图形都这样写。
最后的效果就出现我们想要的粉色边边了
4.画个七巧板
先var个变量tangram出来,这个变量是个数组,有七部分。就是七巧板的七块,每一部分是一个类的对象,具体包括一个p,他也是一个数组。包括每一块的顶点坐标和color属性
//绘制七巧板
var tangram=[
{p:[{x:0,y:0},{x:800,y:0},{x:400,y:400}],color:"#caff67"},
{p:[{x:0,y:0},{x:400,y:400},{x:0,y:800}],color:"#67becf"},
{p:[{x:800,y:0},{x:800,y:400},{x:600,y:600},{x:600,y:200}],color:"#ef3d61"},
{p:[{x:600,y:200},{x:600,y:600},{x:400,y:400}],color:"#f9f51a"},
{p:[{x:400,y:400},{x:600,y:600},{x:400,y:800},{x:200,y:600}],color:"#a594c0"},
{p:[{x:200,y:600},{x:400,y:800},{x:0,y:800}],color:"#fa8ecc"},
{p:[{x:800,y:400},{x:800,y:800},{x:400,y:800}],color:"#f6ca29"},
]
window.onload = function(){
var canvas = document.getElementById("canvas");
canvas.width =800; //可以在JavaScript中定义canvas的大小,优先级更高
canvas.height =800;
var context = canvas.getContext("2d"); //得到绘图的上下文环境,调用方法传入参数,2d绘图
for(var i = 0 ;i < tangram.length ;i++) //使用一个循环,把定义的七巧板数组进行了一次遍历
draw( tangram[i],context) //每一次遍历都调用一次后面的draw函数,传入两个参数:七巧板的一块,绘图的上下文环境
}
function draw(piece,cxt){ //两个参数:piece和context的缩写
cxt.beginPath();
cxt.moveTo( piece.p[0].x , piece.p[0].y ); //顶点坐标的第一个位置
for ( var i = 1 ; i < piece.p.length ; i++) //使用一个循环顺次的使用lineto绘制路径,绘制到后续的坐标
cxt.lineTo( piece.p[i].x , piece.p[i].y );
cxt.closePath(); //closePath结束路径绘制
cxt.fillStyle = piece.color; //在fillStyle属性中调用color
cxt.fill();
cxt.strokeStyle = "black" //给每块添加黑色边边
cxt.lineWidth = 3;
cxt.stroke();
}
5.画个圆
context.arc(
centerx,centery,radius, //圆心x坐标,圆心y坐标,半径
startingAngle,endingAngle, //从哪个弧度值为始结束于哪个弧度值
anticlockwise=false //可选参数,false为默认参数顺时针
)
画一段弧:
var canvas = document.getElementById("canvas");
canvas.width=1024;
canvas.height=768;
var context = canvas.getContext("2d");
context.lineWidth=5
context.strokeStyle="#005588"
//绘制一段弧
context.arc(300,300,200,0,1.5*Math.PI) //状态函数
context.stroke();
画出来是这样的
最终的效果就是这样的:
但是为什么在每段弧首尾会有直线连接呢?因为beginPath()和closePath()会将不封闭的图形闭合掉。
但是如果不写closePath(),就不会出现闭合的线段,而且因为beginPath的存在也不影响下一段路径的绘制,结果就是这样:
当我们在arc函数最后传入参数true使其逆时针旋转时:
再将closePath()去掉:
又到了上色的时间:在代码前调用fillstyle填充颜色
context.fillStyle="#005588"
for (var i = 0; i < 10; i++) { //使用变量i不断移动圆心的位置
context.beginPath()
context.arc(50 + i*100 ,540 , 40 , 0 , 2*Math.PI*(i+1)/10,true) //保持 startingAngle为0不变,到达的位置根据i不断变化
context.closePath();
context.stroke()
context.fill();
}
记得一定要写context.fill()函数。
而且是否有closePath函数最终的图形都是这样:
6.画折线
运用前面的知识我们可以画一个有意思的图形:画一个箭头
//画折线
window.οnlοad=function(){
var canvas = document.getElementById("canvas");
canvas.width=800;
canvas.height=800;
var context = canvas.getContext("2d");
context.moveTo(100,350);
context.lineTo(500,350);
context.lineTo(500,200);
context.lineTo(700,400);
context.lineTo(500,600);
context.lineTo(500,450);
context.lineTo(100,450);
context.lineWidth=10;
context.strokeStyle="#058";
context.stroke();
}
效果如图所示:
如果我们想要绘制多条线段,其中是间断的,灵活的使用多个moveto开头即可,想象有多个虚拟的笔尖一起画。
//分开的折线
window.οnlοad=function(){
var canvas = document.getElementById("canvas");
canvas.width=800;
canvas.height=800;
var context = canvas.getContext("2d");
context.moveTo(100,200);
context.lineTo(300,400);
context.lineTo(100,600);
context.moveTo(300,200);
context.lineTo(500,400);
context.lineTo(300,600);
context.moveTo(500,200);
context.lineTo(700,400);
context.lineTo(500,600);
}
效果如图:
当我们想使三条线有不同的颜色时我们可能会直接在每次绘制之后直接调用strokeStyle给颜色就好了,但是这样的结果就是三条折线全部是最后一个颜色,我们要写将三条线分开就需要使用beginPath(),并在每次绘制完成时调用context.stroke()函数。一定眼分别调用,否则前两个就无法绘制完成。
//分开的折线
window.οnlοad=function(){
var canvas = document.getElementById("canvas");
canvas.width=800;
canvas.height=800;
var context = canvas.getContext("2d");
context.lineWidth=10;
context.beginPath();
context.moveTo(100,200);
context.lineTo(300,400);
context.lineTo(100,600);
context.strokeStyle="pink";
context.stroke();
context.beginPath();
context.moveTo(300,200);
context.lineTo(500,400);
context.lineTo(300,600);
context.strokeStyle="yellow";
context.stroke();
context.beginPath();
context.moveTo(500,200);
context.lineTo(700,400);
context.lineTo(500,600);
context.strokeStyle="#058";
context.stroke();
}
![](https://i-blog.csdnimg.cn/blog_migrate/73b3baad7ec0a81fda5d76aaff76d5ac.png)
关于这段代码有三个需要注意的
1.context.lineWidth=10;定义在代码的最前面,对于beginPath来说,在制定了新的路径再次绘制时,如果前面的属性没有被改变,就会被一直使用,不会因为beginPath被初始化。
2.对于第一条直线,beginPath是可以省略的。但为了维持代码的一致性,还是写上。
3.beginPath表示开始一段全新的路径,moveto表示直接指定一个新的坐标点。不从任何地方开始。lineto表示从上一个坐标点一直画到当前指定的坐标点。当我们用beginPath时第一个moveto也可以直接写成lineto,此时lineto所表示的shangyige清空了,清空不表示从(0,0)开始,而是没有。所以beginPath和lineto在一起其实相当于一次moveto。
canvas绘制是基于状态的用beginpath相当于创建了一个新的路径,可以是用新的状态来进行绘制!