canvas

这篇博客详细介绍了HTML5 Canvas的基础API,包括画线、画矩形、画多边形、画圆、写字、渐变、绘画图片、translate()、scale()、rotate()等,并探讨了自定义参照点旋转、save()和restore()的用法。同时,分享了移动端canvas如何自适应屏幕的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我发现看自己的博客比查文档还快,所以就在这里写一下 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 事件。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值