嗨!大家好,到了每个礼拜的发文时间了(才怪这礼拜已经四篇了XD),今天要来说说[笔记][HTML][JavaScript]canvas的基本用法(3)-最后用滑鼠互动动画做个结尾!这篇文章里稍微提到的极座标。
好的,那什么是极座标?让我们先看看从维基百科里查到的解释:
极座标系(英语:Polar coordinate system)是一个二维座标系统。该座标系统中任意位置可由一个夹角和一段相对原点—极点的距离来表示」
OK,让我们搭配图形,来简单说说这是怎么一回事:
上图中的黑色横线是X
轴、直线是Y
轴,蓝点是座标为(0,0)
的原点,以原点当圆心画一个半径为r
的圆形,这时候我们在圆边上的任一点上标记一个绿点,也就是上文说的极点,将极点与圆心相连画出橘色与紫色的线,当然,这两条线的长度也是圆的半径r
,仔细看一下,这两条线和X
轴之间的夹角不同,会导致线的方向也不一样,在三角函数中中我们称这一角度为θ
他的英文是theta
,唸做夕塔
XD。
那接着我们如果要取得某一极点的座标该怎么做呢?这就要吐出刚刚提到的三角函数了,不过大家不要紧张,我们只需要知道两种而已,那就是正弦sin
和余弦cos
,以下会用最简单的方式来讲解这两个函数求出来的值,那还是先上图:
这是一张非常简单的图,图中蓝点是我们的圆点,t
是夹角θ
,而下边x
是X
轴距离原点的距离,右边的y
则是Y
轴距离原点的距离,在右上方的绿点则是极点,所以我们可以透过三角型可以得知,极点的座标是(原点的X轴座标 + x,原点的y轴座标 + y)
,但我们该怎么知道x
和y
的数值各是多少?先看看以下关于sin
和cos
的公式:
sinθ = y / r
cosθ = x / r
因为除法太不亲民了,所以我们把,公式中的x和三角函数交换位置,转换成乘法:
y = sinθ * r
x = cosθ * r
看起来是不是简单多了!只要我们知道半径r
和sinθ
及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);
这时候我们的太阳会回到上图,只有本体的样子,再来会专注在lightLine
function中,但在这之前先複习一下[笔记][HTML][JavaScript]canvas的基本用法(1)-来绘製一些简单的图形吧!讲的两件事情
JavaScript
中的Math.PI
是代表角度180度。在一个座标中,角度从0度,也就是贴着X轴开始,越下面角度越大,直到绕一圈回到0度,可以参照下图:
複习完毕后,就来画光线吧!先整理一下刚刚讲过的东西,从原点开始到任一极点的线段我们可以把它当成半径r
,而这时候的原点,是太阳的中心;太阳的中心又是跟着滑鼠跑的,所以原点为mouse
物件中的x
和y
,接着试想一下太阳的半径是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();};
如此一来就能够画出从原点到某一极点的线段了!
看了结果后可能你会觉得奇怪,线条的起始点不是应该要距离太阳有些距离的吗?没错!所以我们稍微想一下,目前设定的起始点是原点,如果要让他在太阳的本体外面开始,那要改变哪个数值呢?
嘿嘿!对的!就是半径,既然可以让结束的点用极座标控制在太阳本体之外,那一定也可以让起始点做到一样的事情,刚刚预设结束点的半径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();};
经过上段程式的调整我们会得出上面的太阳,距离太阳一些间隔的线段,这就是我们要的,但还不完全,我们要能够去画出每一个角度的线条,并用迴圈绘製每条线段。
那该怎么得到每个角度呢?目前我们知道的只有代表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();};
如上图,会微妙的发现线段往下偏移了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。
终于找了个时间研究一下极座标这玩意儿,也没想到原来三角函数这么简单XD,这篇应该不会是Canvas
的最后一篇,只是之后可能不会继续用canvas的基本用法基本用法
这个系列名称了,因为之后的可能一点都不基本,哈哈哈,不过如果有还是会继续加上去啦!
之后我会打算做一个小游戏,就之前参加六角学院那个活动的其中一个题目,虽然当时有先交了最低标準的作品出去,但还是会想要把他完成,如果好奇的话可以点这里看设计稿,刚刚看了一下还是觉得很难XD,如果各位大大有什么建议,或经验分享还请留言指教我了,小弟我会感激不尽的
那最后谢谢大家的观看!如果文章中有任何建议、解释错误或是不清楚的地方,都可以留言告诉我,我会尽快修改的!谢谢大家!
参考文章:
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