首页 web前端 H5教程 canvas API ,通俗的canvas基础知识(二)

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

Mar 16, 2017 pm 01:45 PM

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

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

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

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半圆,分别表示顺时针和逆时针,这样就应该清楚了,哦,需要说明的一点就是,画用的方法跟画直线和矩形框的原理是一样的,只是画出了路径,并没有添墨水,仍需用黑白双煞:

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基础知识(四)

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何处理Laravel API报错问题 如何处理Laravel API报错问题 Mar 06, 2024 pm 05:18 PM

标题:如何处理LaravelAPI报错问题,需要具体代码示例在进行Laravel开发时,经常会遇到API报错的情况。这些报错可能来自于程序代码逻辑错误、数据库查询问题或是外部API请求失败等多种原因。如何处理这些报错是一个关键的问题,本文将通过具体的代码示例来演示如何有效处理LaravelAPI报错问题。1.错误处理在Laravel

React API调用指南:如何与后端API进行交互和数据传输 React API调用指南:如何与后端API进行交互和数据传输 Sep 26, 2023 am 10:19 AM

ReactAPI调用指南:如何与后端API进行交互和数据传输概述:在现代的Web开发中,与后端API进行交互和数据传输是一个常见的需求。React作为一个流行的前端框架,提供了一些强大的工具和功能来简化这一过程。本文将介绍如何使用React来调用后端API,包括基本的GET和POST请求,并提供具体的代码示例。安装所需的依赖:首先,确保在项目中安装了Axi

Oracle API集成策略解析:实现系统间无缝通信 Oracle API集成策略解析:实现系统间无缝通信 Mar 07, 2024 pm 10:09 PM

OracleAPI集成策略解析:实现系统间无缝通信,需要具体代码示例在当今数字化时代,企业内部系统之间需要相互通信和数据共享,而OracleAPI就是帮助实现系统间无缝通信的重要工具之一。本文将从OracleAPI的基本概念和原理入手,探讨API集成的策略,最终给出具体的代码示例帮助读者更好地理解和应用OracleAPI。一、OracleAPI基本

学习canvas框架 详解常用的canvas框架 学习canvas框架 详解常用的canvas框架 Jan 17, 2024 am 11:03 AM

探索Canvas框架:了解常用的Canvas框架有哪些,需要具体代码示例引言:Canvas是HTML5中提供的一个绘图API,通过它我们可以实现丰富的图形和动画效果。为了提高绘图的效率和便捷性,许多开发者开发了不同的Canvas框架。本文将介绍一些常用的Canvas框架,并提供具体代码示例,以帮助读者更深入地了解这些框架的使用方法。一、EaselJS框架Ea

Oracle API使用指南:探索数据接口技术 Oracle API使用指南:探索数据接口技术 Mar 07, 2024 am 11:12 AM

Oracle是一家全球知名的数据库管理系统提供商,其API(ApplicationProgrammingInterface,应用程序接口)是一种强大的工具,可帮助开发人员轻松地与Oracle数据库进行交互和集成。在本文中,我们将深入探讨OracleAPI的使用指南,向读者展示如何在开发过程中利用数据接口技术,同时提供具体的代码示例。1.Oracle

uniapp实现如何使用canvas绘制图表和动画效果 uniapp实现如何使用canvas绘制图表和动画效果 Oct 18, 2023 am 10:42 AM

uniapp实现如何使用canvas绘制图表和动画效果,需要具体代码示例一、引言随着移动设备的普及,越来越多的应用程序需要在移动端展示各种图表和动画效果。而uniapp作为一款基于Vue.js的跨平台开发框架,提供了使用canvas绘制图表和动画效果的能力。本文将介绍uniapp如何使用canvas来实现图表和动画效果,并给出具体的代码示例。二、canvas

开发建议:如何利用ThinkPHP框架进行API开发 开发建议:如何利用ThinkPHP框架进行API开发 Nov 22, 2023 pm 05:18 PM

开发建议:如何利用ThinkPHP框架进行API开发随着互联网的不断发展,API(ApplicationProgrammingInterface)的重要性也日益凸显。API是不同应用程序之间进行通信的桥梁,它可以实现数据共享、功能调用等操作,为开发者提供了相对简单和快速的开发方式。而ThinkPHP框架作为一款优秀的PHP开发框架,具有高效、可扩展和易用

Insomnia教程:如何使用PHP API接口 Insomnia教程:如何使用PHP API接口 Jan 22, 2024 am 11:21 AM

PHPAPI接口:如何使用InsomniaInsomnia是一款功能强大的API测试和调试工具,它能够帮助开发者快速、方便地测试和验证API接口,支持多种编程语言和协议,其中包括PHP。本文将介绍如何使用Insomnia测试PHPAPI接口。第一步:安装InsomniaInsomnia是一款跨平台的应用程序,支持Windows、MacOS和Linux等

See all articles