H5新增标签canvas
canvas是 HTML 5
中的新标签
<canvas id="canvas" width=500 height=500>您的浏览器不支持canvas,请升级至最新版</canvas>
这个 HTML 元素是为了客户端矢量图形而设计的。它自己是没有任何行为,但却能够将一个绘图API展现给客户 端,使用
javascript
可以使脚本能够把想绘制的东西绘制到一块画布上。——摘自W3C HTML 中文手册
canvas标签的兼容性
canvas标签在目前主流浏览器都支持。当然,众位都知道有 IE5/6/7/8
的兼容问题,IE9以下的浏览器版本都不支持canvas
canvas的基本图形的绘制
在之前提到了canvas本身是没有任何内容的,需要我们用javascript实现。
- 所以我们需要获取到元素canvas
var canvas=document.getElementById('canvas');
- 获取到元素canvas后,我们需要获取上下文对象,也就是大家说的画笔
var ctx = canvas.getContext('2d');
至此,我们就已经做好了绘制前的准备
直线的绘制
//获取元素
var canvas = document.getElementById("canvas");
//获取上下文对象(画笔)
var ctx = canvas.getContext('2d');
// 1,开始绘制
ctx.beginPath();
// 2,绘制起点
ctx.moveTo(250,250);
// 3,绘制后续的点
ctx.lineTo(500,500);
// 4,结束绘制
// closePath()也叫关闭路径,会把终点和起点连接起来,进行绘制
// 当需要终点和起点连接才会使用closePath()
ctx.closePath();
// 5,画
// 绘制的线和填充的内容会发生覆盖的情况,没有优先级,由代码的顺序决定(后面设置的会覆盖在前面设置的)
// 设置线的宽度
ctx.lineWidth = 5;
//设置线的颜色
ctx.strokeStyle = "red";
// 填充样式
ctx.fillStyle = "#c9c9c9";
ctx.stroke();
// 填充
ctx.fill();
结果如图:
三角形的绘制
我们既然知道了直线的绘制,那么利用直线绘画一个三角线那岂不是易如反掌?
我们只需要多添加一个lineTo即可将其变成三角形
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineTo(500,500);
ctx.lineTo(400,250);
ctx.closePath();
ctx.lineWidth = 5;
ctx.strokeStyle = "red";
ctx.fillStyle = "#c9c9c9";
ctx.stroke();
ctx.fill();
结果如图:
曲线的绘制
曲线的绘制我们可以使用
moveTo()
放置起点使用
quadraticCurverTo()
放置基准点
和终点基准点:曲线偏向的点,曲线的中点会偏向该点
quadraticCurverTo()有四个参数:
参数一:基准点的x坐标
参数二:基准点的y坐标
参数三:终点的x坐标
参数四:终点的y坐标
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
ctx.moveTo(0,0);
ctx.quadraticCurveTo(250,500,500,0);
ctx.stroke();
效果如图:
三次贝塞尔曲线
也许看到这个名字你会很疑惑?这是什么?
但是你看到下面这个图,你就会感觉它非常熟悉
- 其实三次贝塞尔曲线与曲线相比多了一个基准点,这样的解释也许小伙伴们比较容易懂一些
- 方法为:
bezierCurveTo()
bezierCurveTo()共有六个参数
参数一:基准点一的x坐标
参数二:基准点一的y坐标
参数三:基准点二的x坐标
参数四:基准点二的y坐标
参数五:终点的x坐标
参数六:终点的y坐标
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
ctx.moveTo(0,0); ctx.bezierCurveTo(500,0,0,500,500,500);
ctx.stroke();
圆的绘制
以往我们学习数学时,画圆需要的要素有哪些?
圆心?半径?
没错,在这里我们画圆也需要这些,不过也添加了一些
画圆的方法:arc();
arc()的参数为六个:
第一、二个参数为圆心的坐标
参数三:圆的半径
参数四:画笔的起点位置,根据右侧和设置的弧度找到起点
参数五:画笔的终点位置,根据右侧和设置的弧度找到终点
参数六:绘画的方向,true代表着逆时针,false代表着顺时针
在这里我们可以想一想这些能够做到些什么?
像我们平常用到的笑脸?那么那个半圆是怎么做到的呢?这里就需要用到我们的弧度设置了。
在这里我就不做了,感兴趣的朋友可以自己试试改变参数四和参数五来实现
这里是一个圆:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
ctx.beginPath(); ctx.arc(250,250,100,500,250,Math.PI*2,false);
ctx.fillStyle = 'red';
ctx.fill();
结果如图:
绘制一个矩形
绘制矩形方法:strokeRect()
serokeRoct()共有四个参数:
分别为起点的坐标和终点的坐标。
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
ctx.strokeRect(0,0,100,100);
结果如图:
注意
在这里特别声明一下,canvas画布如果画完一个元素后,并没有使用
ctx.closePath()
,那么上一个画完的元素的终点会与下一个绘画元素的起点相连
canvas标签的旋转
细想一下,在CSS3中新推出了transform属性,那么在canvas中是否也有呢?
答案是肯定的。
在CSS中我们经常使用 transform : rotate()
设置旋转度数,单位是deg,那么在canvas中是怎么旋转的呢?
canvas中也拥有 translate()
、 rotate()
、 scaleX()
方法。这些方法可以大大提高我们的效率。
例如,我们现在要制作一个时钟的表盘指向,效果如图:
如果按照直线的画法,我们需要制作12条线,而且坐标还需要经过繁杂的计算。如果我们有旋转的方法呢?
那样的话我们只需要制作一条直线,然后再让它旋转30度,循环11次即可。
在这里提到旋转,就不得不提一下旋转的圆心问题了,在旋转中,如果我们没有设置旋转的原点,那么
默认的原点的坐标
将会是(0,0)
我们将其旋转90度
如下图:
这样不设置原点的旋转,就会造成画布旋转出了原有范围,因为其超出不显示的特性,那样的话,旋转超出的内容将会不在显示。
所以我们就需要设置 旋转的原点
代码如下:
ctx.translate(250, 250);
for (let i = 0; i < 12; i++) {
ctx.rotate(Math.PI / 6);
ctx.beginPath();
ctx.moveTo(0, -200);
ctx.lineTo(0, -150);
ctx.closePath();
ctx.lineWidth = 10;
ctx.stroke();
}
canvas时钟的制作
我们来理一理思路,时钟的制作需要哪些?
时针、分针、秒针
时间刻度
外层圆
时间的获取
那么我们一步步来制作
1 时针、分针、秒针的制作
//时针
cxt.save(); //时针样式
cxt.lineWidth = 7;
cxt.strokeStyle="#000";
cxt.translate(250,250);
cxt.rotate(hour*30*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-140);
cxt.lineTo(0,10);
cxt.stroke();
cxt.closePath();
cxt.restore();
//分针
cxt.save(); //分针样式
cxt.lineWidth = 5;
cxt.strokeStyle="#000";
cxt.translate(250,250);
cxt.rotate(minute*6*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-160);
cxt.lineTo(0,15);
cxt.stroke();
cxt.closePath();
cxt.restore();
//秒针
cxt.save();
cxt.lineWidth = 3;
cxt.strokeStyle="#f00";
cxt.translate(250,250);
cxt.rotate(sec*6*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-185);
cxt.lineTo(0,20);
cxt.stroke();
cxt.closePath();
//画出时针,分针,秒针交叉点
cxt.beginPath();
cxt.strokeStyle="#f00";
cxt.arc(0,0,5,0,360,false);
cxt.fillStyle="#fff"; //填充颜色
cxt.fill(); //填充
cxt.stroke();
cxt.closePath(); //秒针装饰
cxt.beginPath();
cxt.strokeStyle="#f00";
cxt.arc(0,-160,5,0,360,false);
cxt.fill();
cxt.stroke();
cxt.closePath();
cxt.restore();
2 时间刻度(时间刻度需要使用旋转与刻度)
//刻度
//时针刻度
for(var i=0; i<12; i++){
cxt.save(); //设置时针的样式
cxt.lineWidth=7;
cxt.strokeStyle="#000"; //设置异次元空间原点
cxt.translate(250,250); //设置旋转角度
cxt.rotate(i*30*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-170); //画线, 从坐标0,-170开始
cxt.lineTo(0,-190); //到坐标0,-190结束
cxt.stroke();
cxt.closePath();
cxt.restore();
}
//分针刻度
for(var i=0; i<60;i++){
cxt.save();
cxt.lineWidth=5;
cxt.strokeStyle="#000";
cxt.translate(250,250);
cxt.rotate(i*6*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-180);
cxt.lineTo(0,-190);
cxt.stroke();
cxt.closePath();
cxt.restore();
}
3 外层圆
cxt.beginPath(); //画笔开始
cxt.lineWidth = 5; //设置画笔的线宽
cxt.strokeStyle="gold"; //设置画笔的颜色
cxt.arc(250,250,200,0,360,false); //绘制圆形,坐标250,250 半径200,整圆(0-360度),false表示顺时针
cxt.stroke(); //绘图
cxt.closePath(); //结束画布
4 最后是获取时间(我们可以获取当前电脑的本地时间)
//获取时间
var now = new Date(); //定义时间
var sec = now.getSeconds(); //获取秒
var minute = now.getMinutes(); //获取分钟
var hour = now.getHours(); //获取小时
//小时必须获取浮点类型,产生偏移(小时+分钟比)
hour = hour + minute/60; //将24小时转换为12小时
hour=hour>12?hour-12:hour;
最后我们将其整合到一起:
html代码:
<canvas width=500 height=500 style="background:#ccc; display:block; " id="clock">您的浏览器当前版本不支持canvas标签</canvas>
script代码:
var clock = document.getElementById("clock");
var cxt = clock.getContext('2d');
function drawClock(){
cxt.clearRect(0,0,500,500); //清除画布
//获取时间
var now = new Date(); //定义时间
var sec = now.getSeconds(); //获取秒
var minute = now.getMinutes(); //获取分钟
var hour = now.getHours(); //获取小时
//小时必须获取浮点类型,产生偏移(小时+分钟比)
hour = hour + minute/60; //将24小时转换为12小时
hour=hour>12?hour-12:hour;
cxt.beginPath(); //画笔开始
cxt.lineWidth = 5; //设置画笔的线宽
cxt.strokeStyle="gold"; //设置画笔的颜色
cxt.arc(250,250,200,0,360,false); //绘制圆形,坐标250,250 半径200,整圆(0-360度),false表示顺时针
cxt.stroke(); //绘图
cxt.closePath(); //结束画布
//刻度
//时针刻度
for(var i=0; i<12; i++){
cxt.save(); //设置时针的样式
cxt.lineWidth=7;
cxt.strokeStyle="#000"; //设置异次元空间原点
cxt.translate(250,250); //设置旋转角度
cxt.rotate(i*30*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-170); //画线, 从坐标0,-170开始
cxt.lineTo(0,-190); //到坐标0,-190结束
cxt.stroke();
cxt.closePath();
cxt.restore();
}
//分针刻度
for(var i=0; i<60;i++){
cxt.save();
cxt.lineWidth=5;
cxt.strokeStyle="#000";
cxt.translate(250,250);
cxt.rotate(i*6*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-180);
cxt.lineTo(0,-190);
cxt.stroke();
cxt.closePath();
cxt.restore();
}
//时针
cxt.save(); //时针样式
cxt.lineWidth = 7;
cxt.strokeStyle="#000";
cxt.translate(250,250);
cxt.rotate(hour*30*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-140);
cxt.lineTo(0,10);
cxt.stroke();
cxt.closePath();
cxt.restore();
//分针
cxt.save(); //分针样式
cxt.lineWidth = 5;
cxt.strokeStyle="#000";
cxt.translate(250,250);
cxt.rotate(minute*6*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-160);
cxt.lineTo(0,15);
cxt.stroke();
cxt.closePath();
cxt.restore();
//秒针
cxt.save();
cxt.lineWidth = 3;
cxt.strokeStyle="#f00";
cxt.translate(250,250);
cxt.rotate(sec*6*Math.PI/180);
cxt.beginPath();
cxt.moveTo(0,-185);
cxt.lineTo(0,20);
cxt.stroke();
cxt.closePath();
//画出时针,分针,秒针交叉点
cxt.beginPath();
cxt.strokeStyle="#f00";
cxt.arc(0,0,5,0,360,false);
cxt.fillStyle="#fff"; //填充颜色
cxt.fill(); //填充
cxt.stroke();
cxt.closePath(); //秒针装饰
cxt.beginPath();
cxt.strokeStyle="#f00";
cxt.arc(0,-160,5,0,360,false);
cxt.fill();
cxt.stroke();
cxt.closePath();
cxt.restore();
}
//使用setinterval();让时钟动起来
drawClock();
setInterval(drawClock,1000);
结果如图: