0

0

canvas API ,通俗的canvas基础知识(二)

黄舟

黄舟

发布时间:2017-03-16 13:45:23

|

1737人浏览过

|

来源于php中文网

原创

上文我们讲到了画一条线,画矩形,写文字,总算是有了一个好的开头,如果还没有看的同学出门左转,先看看那篇,这里就不多做叙述了,接下来我们看比较复杂的一些属性和方法!

讲之前呢,我还是想温习一下,毕竟上文还有几个属性没有讲到,那我们从画三角形开始吧!

如果看了上文,机智的少年肯定会想到,三角形,多简单啊,无非是比直线多一个点,于是这少年就开始动手了:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.stroke();


呀呵,怎么是一个折线,三角形不是只有三个点吗?是不是因为没有闭合呢?那我再加一个点:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.lineTo(50,50);
ctx.stroke();

哈哈,果然机智如你啊!这个思路其实是正解的,三角形就是这么简单,其实还有一种方式可以画三角形,只需3个点,那就是我们要介绍的:

closePath()闭合路径

有闭合就是开始,一般来说他们是成双成对的

beginPath()开始路径

这对活宝的用法一般是:

ctx.beginPath();

ctx.closePath();

先开始路劲,里面写你要绘制的内容,然后结束路劲,相当于是一个盒子已经封箱了,这样做有个好处就是可以避免绘制过程中的样式污染,你不知道怎么污染?好吧,看下面:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
//第一个三角
ctx.strokeStyle='red';
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.lineTo(50,50);
ctx.stroke();
//第二个三角
ctx.strokeStyle='green';
ctx.moveTo(150,50);
ctx.lineTo(200,100);
ctx.lineTo(150,200);
ctx.lineTo(150,50);
ctx.stroke();

如图,如果我本来是想让第一个三角的颜色为红色,第二个为绿色,但是现在的结果却都是绿色,而且眼尖的同学还看到,第一个三角感觉有2个颜色,颜色也特别的深,感觉是叠了2个三角,你没看到?好,我们改改,你在看:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
//第一个三角
ctx.strokeStyle='red';
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.lineTo(50,50);
//ctx.stroke();
//第二个三角
ctx.strokeStyle='green';
ctx.moveTo(150,50);
ctx.lineTo(200,100);
ctx.lineTo(150,200);
//ctx.lineTo(150,50);
ctx.stroke();

我们先不画第一个三角,也不画第二个三角的左边一边,然后看一下:

第一个三角没有双重色了,说吧绘制了2次,一次红,一次绿,去掉了重绘,后面的颜色也将前面的颜色污染了,这不是我们想要的,这污染,你应该明白了吧!

那我们使用那对活宝看看:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
//第一个三角
ctx.beginPath();
ctx.strokeStyle='red';
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.lineTo(50,50);
ctx.closePath();
ctx.stroke();
//第二个三角
ctx.beginPath();
ctx.strokeStyle='green';
ctx.moveTo(150,50);
ctx.lineTo(200,100);
ctx.lineTo(150,200);
ctx.lineTo(150,50);
ctx.closePath();
ctx.stroke();

这才是我们想要的嘛,你玩你的,我玩我的,互不干扰,(你说画三角只需3个点的呢,吹牛B吧,你看你都是用的4个点),哦,对。

closePath()方法创建从当前点到开始点的路径,这是对此方法的描述,也就是说,使用这个方法,就能将画笔移到beginPath()的位置,这样才能结束画布,所以照这个理论,当画三角时,画到第三个点时,我们用closePath()方法让画笔回到起点,再画线,是不是就闭合了,看看效果:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.beginPath();
ctx.strokeStyle='red';
ctx.moveTo(50,50);
ctx.lineTo(100,100);
ctx.lineTo(50,200);
ctx.closePath();
ctx.stroke();

看,只有三个点,不是折线吧,后面要讲的什么扇形图,不规则图形都可以用此技能,妥妥的!

嗨,也不过如此,你这线条都是一像素的,又不能跟孙悟空的金箍棒一样,要大变大,要小变小,哼,谁说的,哥有神器在手,天下无敌!

我的法宝就是:

lineWidth设置或返回当前的线条宽度

怎么用?哥给一个跟金箍棒:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
vartimer=null;
varnum=1;
ctx.moveTo(150,50);
ctx.strokeStyle='gold';
setInterval(function(){
if(num==100){
clearInterval(timer);
num=1;
}else{
num++;
};
ctx.lineTo(150,100+num*2);
ctx.lineWidth=num;
ctx.stroke();
},100)

金箍棒,大,大,大,大,在大点,哈哈哈~~~
咳咳,严肃点,有此神器,我们就可以修改任何线框,线条的线条宽度了,比如说空心三角形,空心矩形,当然,空心文字你就不要问我了,我不知道~
关于线条,还有另外2个属性:
lineJoin两线交叉的拐角类型
参数:
miter:尖角默认
bevel:斜角
round:圆角

什么意思,那就用空心矩形为例:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.lineWidth=10;
ctx.beginPath();
ctx.lineJoin='miter';
ctx.strokeRect(100,10,80,80);
ctx.closePath();
ctx.beginPath();
ctx.lineJoin='round';
ctx.strokeRect(100,110,80,80);
ctx.closePath();
ctx.beginPath();
ctx.lineJoin='bevel';
ctx.strokeRect(100,210,80,80);
ctx.closePath();

右侧为折线效果

配合折线效果,还有一个属性:

miterLimit规定最大斜接长度。什么意思?看看右边的这个折线图,最下面那组的尖尖角,这个就是斜接,意思通俗意思就是规定那个尖尖角的长度,如果尖尖角的长度小于miterLimit的值,则正常显示,如果大于的话,就会被截掉一部分,其形状就跟lineJoin='bevel'一样一样的,且此方法只对lineJoin="miter"默认值的时候才起作用,给个形象的例子吧:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.lineWidth=10;
ctx.lineJoin="miter";
ctx.beginPath();
ctx.miterLimit=19;
ctx.moveTo(20,20);
ctx.lineTo(150,27);
ctx.lineTo(20,34);
ctx.stroke();

ctx.beginPath();
ctx.miterLimit=18;
ctx.moveTo(20,120);
ctx.lineTo(150,127);
ctx.lineTo(20,134);
ctx.stroke();
ctx.beginPath();
ctx.lineJoin="bevel";
ctx.moveTo(20,220);
ctx.lineTo(150,227);
ctx.lineTo(20,234);
ctx.stroke();

如图,当miterLimit的值大于等于19时,尖尖角正常显示,小于18时,尖尖角被截断了,效果跟设置lineJoin='bevel'是一样的,暂不知道会有什么作用,待以后来发掘!

另一个:
lineCap设置或返回线条的结束端点样式注意,这是设置线条的哦!
参数:
butt默认。向线条的每个末端添加平直的边缘。
round向线条的每个末端添加圆形线帽。
square向线条的每个末端添加正方形线帽。
什么意思?线条嘛,我们还是以金箍棒为例,算了,还是用线条吧(看到金箍棒我就想笑了);

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.lineWidth=10;
ctx.beginPath();
ctx.lineCap='butt';
ctx.moveTo(50,50);
ctx.lineTo(200,50);
ctx.stroke();

ctx.beginPath();
ctx.lineCap='round';
ctx.moveTo(50,100);
ctx.lineTo(200,100);
ctx.stroke();

ctx.beginPath();
ctx.lineCap='square';
ctx.moveTo(50,150);
ctx.lineTo(200,150);
ctx.stroke();

可以看到,后面2个比第一个要长一点,具体长多少呢?画一个图示意一下:

圆角和方脚的原理其实是这样的,很明显多出的一部分的宽度就是线条的一半的长度,所以要精确计算其长度,此小细节需谨记!

现在我们来讲讲画圆及其相关的图形:

arc(x,y,r,sAngle,eAngle,counterclockwise)

什么意思?x,y表示坐标点表示圆心坐标,r表示半径,sAngle表示开始弧度,eAngle表示结束弧度,counterclockwise表示顺时针还是逆时针方式,默认为顺时针false,逆时针为true

注意,这里的角度是用弧度表示的,不是直接写角度,那问题来了,一般我们知道一个圆弧是多少度,怎么知道它是多少弧度呢?总感觉弧度太抽象,嗯嗯,我也有同感,那我们就来科普一下弧度的算法吧,列几个公式(初中,高中的数学,都还给老师了):

1弧度=r;
360°=2∏;
周长C=2∏r;
那么一周的弧度数=2∏r/r=2∏=360°
则1°=2∏*1°/360°=∏*1°/180°(弧度)
90°=∏*90°/180°(弧度)

圆的初始位置是在最右边,跟我们自己手绘圆的起点有那么一点点的不一样,默认是顺时针方向,那角度就应该是如图所示的角度,要是还不清楚的话,我们画2半圆,分别表示顺时针和逆时针,这样就应该清楚了,哦,需要说明的一点就是,画用的方法跟画直线和矩形框的原理是一样的,只是画出了路径,并没有添墨水,仍需用黑白双煞:

MyMap AI
MyMap AI

使用AI将想法转化为图表

下载
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.beginPath();
ctx.arc(80,100,50,0,180*Math.PI/180,false);
ctx.stroke();

ctx.beginPath();
ctx.arc(200,100,50,0,180*Math.PI/180,true);
ctx.stroke();

js里面是没有∏的,你懂的,但是有函数Math.PI,咦,这里为什么是圆弧而不是半圆啊,如果我要画一个半圆怎么弄呢?哈哈~,还记得上面三角形的那个折线吗?这个是一个原理,只是图形没有闭合而已,用closePath()就可以闭合了。

画一个扇形看看,这里我就闭合图形哈:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.beginPath();
ctx.arc(80,100,50,30*Math.PI/180,150*Math.PI/180,false);
ctx.closePath();
ctx.stroke();

当当当当~~~噗,喷了一口老血,怎么是一条小船,说好的扇子呢?再看看三角图形,瞬间就明白了,图形闭合不是以圆心为起始点的,而是初始弧度为起点,然后闭合的时候是回到初始点,就变成小船了,那怎么才能画出一个扇形呢?给个思路,这里暂时不给代码,以后有时间当小实例给到大家,如果我以圆心为起点,画2条直线,连到圆弧的起始点和结束点,是不是就是一个扇形了,哈哈~,不多说了,脑补一下吧,当然,圆弧的起始点的坐标和结束点的坐标计算还是有点费劲的

前面我们画的是空心的圆或弧,可否画实心的呢?貌似问的有点多余,上面说了用黑白双煞,好吧,直接给个一饼好了:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.arc(150,150,50,0,360*Math.PI/180,false);
ctx.fill();

咦,怎么这么像某岛国国旗,还好我用的是默认黑色,嘘嘘,都没看到哈~
还有一个方法可以画圆弧:
arcTo(x1,y1,x2,y2,r)创建两个切线之间的弧/曲线
参数:x1,y1表示第一个坐标,x2,y2表示第二个坐标,r表示曲线半径
两个切线之间的曲线,试试:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(100,20);
ctx.arcTo(150,20,150,70,50);
ctx.lineTo(150,120);
ctx.stroke();

果然是要在两条线段之间写曲线,要是先写2条曲线,在写arcTo(),貌似就出不来了,这让我们想到了moveTo(),lineTo(),再写一个例子:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.moveTo(150,20);
ctx.arcTo(150,200,50,0,20);
ctx.stroke();

想试一下,要是只有一条切线,会怎样?

好大的一个鱼钩啊,看来这样也是可以的,要是没有切线,可否?

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.arcTo(150,200,50,0,20);
ctx.stroke();

额,狗带了,没反应,看来必须至少有一个切线才能画弧线,有个点都行,要求不算高,满足你。

感觉这里始终没有将清楚,arcTo()为什么会画出这样的曲线呢,我觉得有必要画一张图来表示:

它的绘图原理应该是这样的,起始点是圆弧的第一个切点,也是画笔的起始点,然后arcTo的两个坐标点分别是圆弧的起点和终点,这样3个点就形成了2天相交的线,然后以半径为r画一个圆,与这2条线相切,2个切点就是绘制的这条弧,而第二张图就是arcTo()所绘制的图形,为了证实这一点,我们写一个相近的图形来看看:

varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.beginPath();
ctx.fillRect(100,100,5,5);
ctx.fillRect(180,80,5,5);
ctx.fillRect(160,180,5,5);
ctx.moveTo(62,112);
ctx.lineTo(182,82);
ctx.lineTo(162,182);
//这里是绘制切线弧
ctx.moveTo(103,103);
ctx.arcTo(183,83,162,182,40);
ctx.stroke();

对比这2组图,将生成的弧线用圆对比一下,会发现起点并不是切点,但基本思路是正确的,3点形成一个夹角,然后以r为圆心,画一个圆,从起点到第二个切点,就是arcTo()方法所绘制的图形。

今天就到这吧!讲的很混乱,东一脚西一脚的,希望你们能懂!最希望的是能对你们有帮助,那就再好不过了!

 以上就是canvas API ,通俗的canvas基础知识(二) 的内容,更多相关内容请关注PHP中文网(www.php.cn)!

相关文章:

canvas API 介绍,常见的canvas基础知识(一)

canvas API 介绍,常见的canvas基础知识(三)

canvas API 介绍,常见的canvas基础知识(四)

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

2

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

1

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

1

2026.01.31

golang 循环遍历
golang 循环遍历

本专题整合了golang循环遍历相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.31

Golang人工智能合集
Golang人工智能合集

本专题整合了Golang人工智能相关内容,阅读专题下面的文章了解更多详细内容。

1

2026.01.31

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

76

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

73

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

67

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

19

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Canvas 绘制时钟
Canvas 绘制时钟

共7课时 | 1.5万人学习

HTML5新特性基础视频教程
HTML5新特性基础视频教程

共18课时 | 3.2万人学习

HTML5 Canvas 动画实战教程
HTML5 Canvas 动画实战教程

共28课时 | 6.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号