canvas 多边形,

  canvas 多边形,

  起因

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

  做完例子,我想到如果是四分或者五分会是什么样子。

  我重写了代码,改变了点数。最终的效果是实现各个点最后的拉伸运动来达到平衡,但是点与点之间的连线不是很好看,有些是交叉的。

  所以我想知道我是否可以优化这个作品。

  旋转连线

  上例中的点都在随机位置,所以连接是不可控的。所以我想先从这个开始。

  先以某一点为参考点,求出其他点相对于该点的角度。

  然后把这些点按照角度从小到大连接起来,就可以画出一个正多边形了。

  大致的实现代码如下:

  设balls=[];设ball num=6;设firstBall=nullwhile(Ball num-){ let Ball=new Ball(20,parse color(math . random()*0x ffffff))Ball . x=math . random()* width;ball . y=math . random()* height;balls.push(ball) if(!first ball){ first ball=ball . angle=0 } else { const dx=ball . x-first ball . x,dy=ball . y-first ball . y;ball.angle=Math.atan2(dy,dx);} }//尽量让球连接是正多边形balls=balls.sort ((balla,ballb)={ return balla . angle-ballb . angle })这样在最后画连接时,遍历数组就可以按照角度从小到大来画了。

  效果如下:

  这样可以大大减少越线的情况,但不能完全避免。

  接下来,我想尝试优化这个方案。比如angle用Math.abs来对齐,或者每个点找角度最小的点来连接。但结果是不行的,越线是避不开的。

  基于中心点旋转

  后来,我想到了一个主意。如果可以确定多边形的中心点,那么就可以分别计算出各点相对于中心点的角度,并且可以顺时针或逆时针连接这些点。

  但是在网上搜索了很久,所有的算法都需要一系列按照一定时针顺序排列的点。

  但是如果我有这些点,我已经可以画多边形了。不得不放弃。

  X轴两极点分割

  无奈之下只好找了Google,然后在知乎上找到了一个不错的答案:如何将平面上的一组无序点连接成一个简单的多边形?

  具体算法描述,看那个回答就行了,不赘述。

  但在连接上链和下链时,其实只要按X轴降序连接上链,X轴升序连接下链(逆时针画)。至于X轴相同的点,优先Y轴大还是小都可以。

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

  在判断一个点属于上链还是下链时,首先想到的是根据两点确定直线的函数方程,然后引入点的坐标进行计算。不过我后来觉得,所有的点都是以最左边的极点来计算,然后按照角度来划分,直观上更好理解。

  大致的代码如下:

  设balls=[];让tempBalls=[];设球数=6;设isDragingBall=false while(Ball num-){ let Ball=new Ball(10,parse color(math。random()*0x ffffff))球。x=数学。random()*宽度;球。y=数学。random()*高度;tempBalls.push(ball)}//让点按X轴升序排序临时球=临时球。sort((ballA,ballB)={ return ballA。x球b。x })//找X轴左右极点设firstBall=tempBalls[0],last ball=tempBalls[tempBalls。长度-1];让小xbols=temp球。过滤器(球=球。x===第一球。x),大xbols=临时球。过滤器(球=球。x===最后一个球。x)//处理左右极点有多个的情况如果(小xbols。长度1){小xbols。sort((ballA,ballB)={ return ballB。你好巴拉。y })} if(大xbols。长度1){大xbols。sort((ballA,ballB)={ return ballB。你好巴拉。y })}第一个球=小xbols[0]最后一个球=大xbols[0]//获得极点连线的角度让分割线角度=数学。atan2(最后一球。第一个球。y,最后一个球。第一个球。x);设上界球=[],下界球=[];//所有其他点跟第一球计算角度//大于分割线角度的都是下链//其他是上链tempballs。foreach(ball={ if(ball===第一个球 ball===最后一个球){ return false } let angle=math。阿坦2(球。第一个球。y球。第一个球。x);if(角度分模线角度){下球。推(球)} else {上球。推(球)})//处理X轴相同情况的排序低球=低球。sort((ballA,ballB)={ if (ballA.x!==ballB。x){返回巴拉。x球b。x }回球b。你好巴拉。y })上球=上球。sort((ballA,ballB)={ if (ballA.x!==ballb。x){返回ballb。x巴拉。x }回球b。y-ballb。x })//逆时针连接所有的点balls=[第一球].concat(下部球,[lastBall],上部球)balls=balls。地图((球,我)={球。text=I 1;回球})最终返回的蛋蛋,就是按逆时针排序的多边形的点了。

  效果如下:

  各个球的内部状态如下:

  以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: