[笔记][HTML][JavaScript]canvas的基本用法(4)-一点都不基本的极座标!

嗨!大家好,到了每个礼拜的发文时间了(才怪这礼拜已经四篇了XD),今天要来说说[笔记][HTML][JavaScript]canvas的基本用法(3)-最后用滑鼠互动动画做个结尾!这篇文章里稍微提到的极座标。


好的,那什么是极座标?让我们先看看从维基百科里查到的解释:

极座标系(英语:Polar coordinate system)是一个二维座标系统。该座标系统中任意位置可由一个夹角和一段相对原点—极点的距离来表示」

OK,让我们搭配图形,来简单说说这是怎么一回事:
http://img2.58codes.com/2024/20106935K9QKfu2G4O.jpg
上图中的黑色横线是X轴、直线是Y轴,蓝点是座标为(0,0)的原点,以原点当圆心画一个半径为r的圆形,这时候我们在圆边上的任一点上标记一个绿点,也就是上文说的极点,将极点与圆心相连画出橘色与紫色的线,当然,这两条线的长度也是圆的半径r,仔细看一下,这两条线和X轴之间的夹角不同,会导致线的方向也不一样,在三角函数中中我们称这一角度为θ他的英文是theta,唸做夕塔XD。

那接着我们如果要取得某一极点的座标该怎么做呢?这就要吐出刚刚提到的三角函数了,不过大家不要紧张,我们只需要知道两种而已,那就是正弦sin和余弦cos,以下会用最简单的方式来讲解这两个函数求出来的值,那还是先上图:
http://img2.58codes.com/2024/20106935r6uECuFCms.jpg
这是一张非常简单的图,图中蓝点是我们的圆点,t是夹角θ,而下边xX轴距离原点的距离,右边的y则是Y轴距离原点的距离,在右上方的绿点则是极点,所以我们可以透过三角型可以得知,极点的座标是(原点的X轴座标 + x,原点的y轴座标 + y),但我们该怎么知道xy的数值各是多少?先看看以下关于sincos的公式:

sinθ = y / r
cosθ = x / r

因为除法太不亲民了,所以我们把,公式中的x和三角函数交换位置,转换成乘法:

y = sinθ * r
x = cosθ * r

看起来是不是简单多了!只要我们知道半径rsinθcosθ,就有办法取得任一极点的座标,也就是今天的主题极座标。

也许你会想说,我知道半径r,但我对那个sinθcosθ实在不晓得该怎么办才好,放心在JavaScript中这两个函数已经妥妥的準备好!剩下的就是动手实做!让我们来做个简单的小例子吧!

以上一次的太阳为例子来重新绘製他身边的光线,我先删减了背景颜色变化和之前绘製光线的部分,只留下太阳的本体,程式码如下:
HTML

<canvas id="myCanvas"></canvas>

JavaSript

let canvas = document.getElementById("myCanvas");let ctx = canvas.getContext("2d");//纪录滑鼠位置let mouse = {    x : 0,    y : 0,};//监听滑鼠事件window.addEventListener('mousemove',(event) => {    mouse.x = event.pageX;    mouse.y = event.pageY;});//一个绘製的functionconst draw = () =>{    //把视窗大小重新设定给canvas    canvas.height = window.innerHeight;    canvas.width = window.innerWidth;        ctx.clearRect(0, 0, canvas.width, canvas.height);        //之后绘製太阳    ctx.beginPath();    ctx.arc(mouse.x,mouse.y,30,0,Math.PI*2);    ctx.strokeStyle="#FF5511";    ctx.stroke();    ctx.fillStyle="#FFFF00";    ctx.fill();        //绘製光芒线条    lightLine();};//绘製光芒线条的functionconst lightLine = () =>{    };//每隔50毫秒重新绘製一次setInterval('draw()',50);

http://img2.58codes.com/2024/20106935HstW3pFHPR.jpg
这时候我们的太阳会回到上图,只有本体的样子,再来会专注在lightLinefunction中,但在这之前先複习一下[笔记][HTML][JavaScript]canvas的基本用法(1)-来绘製一些简单的图形吧!讲的两件事情

JavaScript中的Math.PI是代表角度180度。在一个座标中,角度从0度,也就是贴着X轴开始,越下面角度越大,直到绕一圈回到0度,可以参照下图:
http://img2.58codes.com/2024/20106935otJE60FQqb.jpg

複习完毕后,就来画光线吧!先整理一下刚刚讲过的东西,从原点开始到任一极点的线段我们可以把它当成半径r,而这时候的原点,是太阳的中心;太阳的中心又是跟着滑鼠跑的,所以原点为mouse物件中的xy,接着试想一下太阳的半径是30,光线又一定会超越太阳本身,所以r的长度会大于30,这里先给定60,有了原点、半径后,我们还需要角度,不过现阶段我们先设角度为0,绘製出如同X轴的右线:
JavaScript

//绘製光芒线条的functionconst lightLine = () =>{    //开始绘图    ctx.beginPath();    //开始点为原点,滑鼠目前的所在座标    ctx.moveTo(mouse.x,mouse.y);        //从原点到某一极座标,用文章开头说的公式带入数字,设角度为0,r为60,取得X轴及Y轴    //求X的公式为x = cosθ * r    let X = Math.cos(0) * 60;    //求y的公式为x = sinθ * r    let Y = Math.sin(0) * 60;        //上方取得的X及Y为从原点到某一极点的距离,所以我们把原点的所在座标加上该数值    ctx.lineTo(mouse.x + X,mouse.y + Y);    ctx.stroke();};

如此一来就能够画出从原点到某一极点的线段了!
http://img2.58codes.com/2024/20106935C24edNr19X.jpg
看了结果后可能你会觉得奇怪,线条的起始点不是应该要距离太阳有些距离的吗?没错!所以我们稍微想一下,目前设定的起始点是原点,如果要让他在太阳的本体外面开始,那要改变哪个数值呢?

半径角度

嘿嘿!对的!就是半径,既然可以让结束的点用极座标控制在太阳本体之外,那一定也可以让起始点做到一样的事情,刚刚预设结束点的半径r是60,那我们让起始点的半径r大于太阳的半径30一点点,就设定为40。以下程式:
JavaScript

const lightLine = () =>{    ctx.beginPath();    //把r设为40取x轴和y轴距离原点的距离    let X = Math.cos(0) * 40;    let Y = Math.sin(0) * 40;    //用原点加上该距离    ctx.moveTo(mouse.x + X,mouse.y + Y);        //结束点不变    X = Math.cos(0) * 60;    Y = Math.sin(0) * 60;    ctx.lineTo(mouse.x + X,mouse.y + Y);    ctx.stroke();};

http://img2.58codes.com/2024/20106935ANWNMMRs00.jpg
经过上段程式的调整我们会得出上面的太阳,距离太阳一些间隔的线段,这就是我们要的,但还不完全,我们要能够去画出每一个角度的线条,并用迴圈绘製每条线段。

那该怎么得到每个角度呢?目前我们知道的只有代表180度的Math.PI,如果今天要得到60度,可以用360度,也就是先把Math.PI*2(180度乘上2)后在除于6来处理,但是如果要取的角度是17度呢?147度?273度?该怎么办?就用比例原则吧!

所谓的比例原则,就是先得出该角度占了360度的多少。以17度为例,用17/360来算出该角度在360度中的比例,大约是0.047222...左右,那在以这个数字去乘回代表360度的Math.PI*2就有办法取得任一圆的任一角度!我们把这个公式带进程式中:
JavaScript

const lightLine = () =>{    ctx.beginPath()    //设定一个变数为角度    let t = 0;    //假设我们要画夹角为17度的线段    t = 17    /*把计算cosθ和sinθ的切出来    并以角度t除上360度取得比例后在乘上Math.PI*2获得角度    */    let cosT = Math.cos((t/360) * (Math.PI*2))    let sinT = Math.sin((t/360) * (Math.PI*2))        let X = cosT * 40;    let Y = sinT * 40;    ctx.moveTo(mouse.x + X,mouse.y + Y);        X = cosT * 60;    Y = sinT * 60;    ctx.lineTo(mouse.x + X,mouse.y + Y);    ctx.stroke();};

http://img2.58codes.com/2024/20106935A97GepX1kp.jpg
如上图,会微妙的发现线段往下偏移了17度。那现在各位大大们应该已经了解极座标了!剩下光芒线条,就可以直接用迴圈处理:

const lightLine = () =>{    ctx.beginPath()        //把角度t放到迴圈中,从0开始到360度,每隔20度就画绘製一条光线    for(let t=0;t<360;t+=20){        let cosT = Math.cos((t/360) * (Math.PI*2))        let sinT = Math.sin((t/360) * (Math.PI*2))        let X = cosT * 40;        let Y = sinT * 40;        ctx.moveTo(mouse.x + X,mouse.y + Y);        X = cosT * 60;        Y = sinT * 60;        ctx.lineTo(mouse.x + X,mouse.y + Y);        ctx.stroke();    };};

登愣!使用极座标绘製的太阳完成了!有没有觉得用这种方式绘製出来的光线比较自然XD,如果要增加或减少线条的话,主要是在t+=20这个地方做设置,如果希望光线密集一点,就让间隔的角度小一些,如果希望他宽鬆一点,就加大间隔,小弟我在此附上CodePen连结,如果有兴趣的话可以试试看他的变化,基本上就和上次的差不多XD。
http://img2.58codes.com/2024/20106935t6TWRsY0yh.jpg


终于找了个时间研究一下极座标这玩意儿,也没想到原来三角函数这么简单XD,这篇应该不会是Canvas的最后一篇,只是之后可能不会继续用canvas的基本用法基本用法这个系列名称了,因为之后的可能一点都不基本,哈哈哈,不过如果有还是会继续加上去啦!

之后我会打算做一个小游戏,就之前参加六角学院那个活动的其中一个题目,虽然当时有先交了最低标準的作品出去,但还是会想要把他完成,如果好奇的话可以点这里看设计稿,刚刚看了一下还是觉得很难XD,如果各位大大有什么建议,或经验分享还请留言指教我了,小弟我会感激不尽的http://img2.58codes.com/2024/emoticon41.gif

那最后谢谢大家的观看!如果文章中有任何建议、解释错误或是不清楚的地方,都可以留言告诉我,我会尽快修改的!谢谢大家!

参考文章:

https://zh.wikipedia.org/wiki/%E6%9E%81%E5%9D%90%E6%A0%87%E7%B3%BBhttps://zh.wikipedia.org/wiki/%E4%B8%89%E8%A7%92%E5%87%BD%E6%95%B0

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章