我发现看自己的博客比查文档还快,所以就在这里写一下 canvas 基础的API。以及我自己封装的画笔,github地址
基础API
画线
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.moveTo(20, 20); //画笔移动到这个坐标开始画
ctx.lineTo(200, 100); //画笔画到哪里
ctx.strokeStyle = 'red';
ctx.lineWidth = 10; //线粗细
ctx.lineCap = 'round'; //线两端圆角,默认直角
ctx.stroke(); //画路径(线)
效果
画矩形
带描边的
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(20, 20, 100, 60) //fillRect(起始x坐标,起始y坐标,宽,高)
ctx.strokeStyle = 'blue';
ctx.lineWidth = 10; //描边粗细
ctx.lineJoin = 'round'; //圆角,默认直角
ctx.strokeRect(15, 15, 110, 70) //受路径画法的影响,这里参数稍有不同
效果
画多边形
举例三角形
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.moveTo(20, 20);
ctx.lineTo(200, 100);
ctx.lineTo(60, 100);
ctx.closePath(); //关闭路径
// ctx.stroke(); //画路径
ctx.fill(); //填充
效果
beginPath()
绘画时可以使用 beginPath() 开启一个新的状态,类似作用域。举例:
ctx.lineWidth = 10;
ctx.strokeStyle = 'red';
ctx.moveTo(100, 50);
ctx.lineTo(300, 50);
ctx.stroke();
ctx.strokeStyle = 'green';
ctx.moveTo(100, 100);
ctx.lineTo(300, 100);
ctx.stroke();
ctx.strokeStyle = 'blue';
ctx.moveTo(100, 150);
ctx.lineTo(300, 150);
ctx.stroke(); //其实一个作用域下,一个stroke()就可以了
加上beginPath()
ctx.lineWidth = 10;
ctx.strokeStyle = 'red';
ctx.moveTo(100, 50);
ctx.lineTo(300, 50);
ctx.stroke(); //这里每个作用域都要stroke()
ctx.beginPath();
ctx.strokeStyle = 'green';
ctx.moveTo(100, 100);
ctx.lineTo(300, 100);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = 'blue';
ctx.moveTo(100, 150);
ctx.lineTo(300, 150);
ctx.stroke();
画圆
首先注意canvas中画圆用的是弧度而不是角度,但一般情况下角度对我们来说更直观,所以需要将角度转成弧度,很简单,一个圆角度为360,而弧度为2π,写个函数转换一下就行。
//角度转弧度,angle to radian
function a2r(angle){
return angle*Math.PI/180;
}
然后还有个注意事项是canvas中画圆中角度0度是在正上方,而弧度0度在正右方(也就是说画圆弧默认会在正右方开始),所以要想从正上方开始画那就写初始弧度为 -90*Math.PI/180。
下面随便画个饼状图:
ctx.fillStyle = '#fe58fd';
ctx.beginPath();
ctx.moveTo(200, 100); //圆心
ctx.arc(200, 100, 50, a2r(0), a2r(166)); //arc(圆心x,圆心用,半径,初始弧度,结束弧度)
ctx.fill();
ctx.beginPath();
ctx.fillStyle = '#7dff00';
ctx.moveTo(200, 100);
ctx.arc(200, 100, 50, a2r(166), a2r(236));
ctx.fill();
ctx.beginPath();
ctx.fillStyle = '#0000ee';
ctx.moveTo(200, 100);
ctx.arc(200, 100, 50, a2r(236), a2r(0));
ctx.fill();
效果
写字
ctx.font = '30px Microsoft YaHei';
ctx.textBaseline = 'top'; //默认值为alphabetic,相对于strokeText()或fillText()的起始x坐标
ctx.textAlign = 'left'; //默认值为start,相对于strokeText()或fillText()的起始y坐标
ctx.strokeText('Hello Sam', 20, 20); //(文本内容,起始x,起始y)
// ctx.fillText('Hello Sam', 20, 20);
console.log(ctx.measureText('Hello Sam'))//获取该文本宽度
效果
渐变
圆渐变
var grd=ctx.createRadialGradient(75,50,5,75,50,70); //(内圆心x,内圆心y,内圆半径,外圆心x,外圆心y,外圆半径)
grd.addColorStop(0,"red"); //(0-1之间,css色值)
grd.addColorStop(1,"white");
ctx.fillStyle=grd;
ctx.fillRect(10,10,150,100);
效果
径向渐变
var grd=ctx.createLinearGradient(0,0,170,0); //(渐变开始点x,渐变开始点y,渐变结束点x,渐变结束点x)
grd.addColorStop(0,"black");
grd.addColorStop(1,"white");
ctx.fillStyle=grd;
ctx.fillRect(20,20,150,100);
效果
绘画图片
正常绘画
var img = new Image();
img.src = 'http://www.w3school.com.cn/i/eg_tulip.jpg';
img.onload = function(){
ctx.drawImage(img, 0, 0); //(图片对象,起始x,起始y)
}
缩放
var img = new Image();
img.src = 'http://www.w3school.com.cn/i/eg_tulip.jpg';
img.onload = function(){
ctx.drawImage(img, 0, 0, 200, 100); //(图片对象,起始x,起始y, 图片宽度,图片高度)
}
裁剪
var img = new Image();
img.src = 'http://www.w3school.com.cn/i/eg_tulip.jpg';
img.onload = function(){
//裁剪图片(源,从原图哪里开始裁剪x坐标,y坐标,要裁剪宽度,高度,在画布上开始x坐标,y坐标,裁剪后缩放对比裁剪的宽高)
ctx.drawImage(img, 100, 0, 160, 100, 20, 20, 160, 100);
}
translate()画布偏移
注意:是画布偏移而不是图形偏移。一般坐标原点在画布左上角 (0, 0),如果 ctx.translate(100, 100) 相当于将画布原点移到了原来画布上的(100, 100)。比如:
ctx.fillStyle = 'violet';
ctx.fillRect(0, 0, 100, 50);
ctx.translate(110, 60);
ctx.fillRect(0, 0, 100, 50);
同样是 ctx.fillRect(0, 0, 100, 50),使用 translate() 后的画布原点产生了偏移。
scale()画布缩放
注意:也是画布缩放而不是图形缩放。scale(2, 2) 相当于将原来画布 x、y 坐标比例都放大了两倍。比如:
ctx.strokeStyle = 'violet';
ctx.strokeRect(100, 0, 100, 50);
ctx.scale(2, 2);
ctx.strokeRect(100, 0, 100, 50);
图中可以看出,scale(2,2) 之后,矩形的起始点和坐标和宽高视觉上都是是原画布的两倍。
rotate()画布旋转
注意:也是画布旋转而不是图形旋转,旋转参考点默认是画布原点。比如:
ctx.strokeStyle = 'violet';
ctx.strokeRect(100, 0, 100, 50);
ctx.moveTo(0, 0);
ctx.lineTo(200, 0);
ctx.stroke();
ctx.rotate(30 * Math.PI/180); //顺时针旋转30度
ctx.strokeRect(100, 0, 100, 50);
ctx.moveTo(0, 0);
ctx.lineTo(200, 0);
ctx.stroke();
图中可以看出,rotate(30*Math.PI/180) 后,整个画布都顺时针旋转了30度。
自定义参照点旋转
rotate() 参照点是画布原点,但显然这不是我们想要的,我们应该自定义参照点旋转,这里需要 translate() 与 rotate() 配合。下面列举两种方法,这里以画矩形为例,假设我们要画矩形 strokeRect(100,100,200,80),以该矩形中心点旋转30度:
// 第一种先偏移到参照点,再旋转,在偏移回来
ctx.strokeRect(100, 100, 200, 80);
ctx.strokeStyle = 'red';
// 偏移到参照点
ctx.translate(200, 140);
ctx.rotate(30 * Math.PI/180);
// 偏移回来
ctx.translate(-200, -140);
ctx.strokeRect(100, 100, 200, 80);
// 第二种思路是先将参照点移到与画布原点重合,再旋转,在偏移到图形原来的位置
ctx.strokeRect(100, 100, 200, 80);
ctx.strokeStyle = 'red';
ctx.translate(200, 140);
ctx.rotate(30 * Math.PI/180);
// 这里以矩形为例,起始点x要减去参照点x坐标,起始点y要减去参照点y坐标
ctx.strokeRect(-100, -40, 200, 80);
上面代码中两种方法的实现效果
save()和restore()
我们知道了上面几个改变画布的方法会时画布产生变形,所以出现了save() 和 restore() (成对使用),用于恢复画布状态。使用方式大概是:
ctx.strokeStyle = 'violet';
ctx.save(); //保存之前画布状态(本行代码之前的)
ctx.translate(100, 100);
ctx.strokeRect(0, 0, 100, 50);
ctx.restore(); //恢复画布状态
ctx.strokeRect(0, 0, 100, 50);
移动端canvas自适应屏幕
js直接设置 canvas.width 和 canvas.height 即可。
canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;
//或者
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
或者监听 onresize 事件。