画布里面怎么基于随机点绘制一个多边形

  介绍

这篇文章主要介绍画布里面怎么基于随机点绘制一个多边形,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

<强>起因

今天在学习《HTML5 + Javascript动画基础》这本书的时候,在第八章的第三节讲到如何用三个弹簧连接三个点来做拉伸运动。

在做完例子之后,就想到如果是四个点,五个点,怎么样。

就改写了一下代码,把点的数目变量化。最终的效果是能实现各个点最终的拉伸运动到平衡,可是点之间的连线不是很好看,有些是交叉的。

画布里面怎么基于随机点绘制一个多边形

于是就想着能不能优化这一块。

<>强旋转连线

前面例子里面的点,都是随机位置,所以连线不可控。所以想先从这块着手。

先以某一个点为参照点,获得其他点相对于这个点的角度。

然后按照角度从小到大的去连接这些点,这样就能画出一个正常的多边形了。

大致实现代码如下:

let  balls =, [];   let  ballNum =, 6;   let  firstBall =,空;   而(ballNum——), {   let 才能;ball =, new 球(20日,parseColor (math . random (), *, 0 xffffff))   ball.x 才能=,math . random(), *,宽度;   ball.y 才能=,math . random(), *,高度;   balls.push才能(球)      if 才能;(! firstBall), {   ,,,firstBall =球   ,,,ball.angle =0   ,,},{else    ,,,const  dx =, ball.x 作用;firstBall.x,   ,,,,,,,,,dy =, ball.y 作用;firstBall.y;      ,,,ball.angle =, Math.atan2 (dy, dx);   ,,}   }//,尝试让球连线是一个正多边形   时间=balls  balls.sort ((ballA, ballB),=祝辞,{   return 才能;ballA.angle 安康;ballB.angle   })

这样在最后绘制连线的时候,遍历数组就能按照角度从小到大来绘制了。

效果如下:

画布里面怎么基于随机点绘制一个多边形

这样是能极大的减少交叉线的情况,可还是无法完全避免。

接下来,想尝试优化这个方案,比如角度用数学。abs来取正,或者每一个点都找夹角最小的点来连线。可是结果都不行,无法避免交叉线。

<>强基于中心点旋转

后面又想到一个思路,如果能确定多边形的中心点,那么分别计算所有点相对于中心点的夹角,就能以顺时针或者逆时针来连接这些点。

可是在网上找了半天,所有点算法里面,都是要求有一系列按某个时针顺序排列的点。

可是如果我有这些点,就已经能绘制多边形了。只好放弃

<强> X轴两极点分割

无奈之下只好找谷歌,然后就发现了知乎上的一个答案挺好的:如何将平面上无序的一组点连成一个简单多边形?

具体算法描述,大家看那个答案就好,我就不赘述了。

不过在连接上链和下链的时候,其实只要保证上链是X轴降序连接,下链是X轴升序连接即可(以逆时针方向绘制)。至于X轴相同的点,不管是优先Y轴大的还是小的都可以。

实现的时候,是严格按照答案里面的算法实现的。

在判断一个点是属于上链还是下链的时候,一开始想的是基于两点确定直线的函数方程,再引入点的坐标来计算。不过后面想的到,所有的点都以最左边的极点来计算斜角,然后根据角度大小来划分,视觉上更好理解。

大致代码如下:

let  balls =, [];   let  tempBalls =, [];   let  ballNum =, 6;   let  isDragingBall =,假;      而(ballNum——), {   let 才能;ball =, new 球(10,parseColor (math . random (), *, 0 xffffff))   ball.x 才能=,math . random(), *,宽度;   ball.y 才能=,math . random(), *,高度;   tempBalls.push才能(球)   }//,让点按X轴升序排序   时间=tempBalls  tempBalls.sort ((ballA, ballB),=祝辞,{   return 才能;ballA.x 安康;ballB.x   })//,找X轴左右极点   let  firstBall =, tempBalls [0],   ,,,lastBall =, tempBalls [tempBalls.length  1];   let  smallXBalls =, tempBalls.filter (ball =祝辞,ball.x ===, firstBall.x),   ,,,bigXBalls =, tempBalls.filter (ball =祝辞,ball.x ===, lastBall.x)//,处理左右极点有多个的情况   if  (smallXBalls.length 祝辞,1),{   smallXBalls.sort才能((ballA, ballB),=祝辞,{   ,,,return  ballB.y 作用;ballA.y   })才能   }   if  (bigXBalls.length 祝辞,1),{   bigXBalls.sort才能((ballA, ballB),=祝辞,{   ,,,return  ballB.y 作用;ballA.y   })才能   }      时间=firstBall  smallXBalls [0]   时间=lastBall  bigXBalls [0]//,获得极点连线的角度   let  splitLineAngle =, Math.atan2 (lastBall.y 安康;firstBall.y, lastBall.x 作用;firstBall.x);   let  upperBalls =, [],   ,,,lowerBalls =, [];//,所有其他点跟firstBall计算角度//,大于splitLineAngle的都是下链//,其他是上链   tempBalls.forEach (ball =祝辞,{   if 才能;(ball ===, firstBall  | |, ball ===, lastBall), {   ,,,return 错误的   ,,}   let 才能;angle =, Math.atan2 (ball.y 安康;firstBall.y, ball.x 作用;firstBall.x);   if 才能;(angle 祝辞,splitLineAngle), {   ,,,lowerBalls.push(球)   ,,},{else    ,,,upperBalls.push(球)   ,,}   })//,处理X轴相同情况的排序   时间=lowerBalls  lowerBalls.sort ((ballA, ballB),=祝辞,{   if 才能;(ballA.x  !==, ballB.x), {   ,,,return  ballA.x 作用;ballB.x   ,,}   return 才能;ballB.y 安康;ballA.y   })      时间=upperBalls  upperBalls.sort ((ballA, ballB),=祝辞,{   null   null   null   null   null   null   null   null   null   null   null   null   null

画布里面怎么基于随机点绘制一个多边形