百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>html5教程> 怎样在canvas里面基于随机点绘制一个多边形-
分享文章到:

怎样在canvas里面基于随机点绘制一个多边形-

发布时间:09/01 来源:未知 浏览: 关键词:
这篇文章主要介绍了canvas里面怎样基于随机点绘制一个多边形的办法的相干材料,内容挺不错的,此刻分享给大家,也给大家做个参照 。 这篇文章主要介绍了canvas里面怎样基于随机点绘制一个多边形的办法的相干材料,内容挺不错的,此刻分享给大家,也给大家做个参照 。

因由

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

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

就改写了一下代码,把点的数量变量化。终究的结果是能实现各个点终究的拉伸运动到均衡,可是点之间的连线不是非常不错看,有些是穿插的。

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

扭转连线

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

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

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

大致实现代码如下:

let balls = [];
let ballNum = 6;
let firstBall = null;
while(ballNum--) {
  let ball = new Ball(20, parseColor(Math.random() * 0xffffff))
  ball.x = Math.random() * width;
  ball.y = Math.random() * height;
  balls.push(ball)

  if (!firstBall) {
    firstBall = ball
    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
})

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

结果如下:

这样是能极大的减少穿插线的状况,可还是没法完全以免。

接下来,想尝试优化这个方案,比方angle用Math.abs来取正,或者每一个点都寻夹角最小的点来连线。可是效果都不过关,没法以免穿插线。

基于核心点扭转

背面又想到一个思绪,要是能肯定多边形的核心点,那么离别盘算所有点相关于核心点的夹角,就能以顺时针或者逆时针来连贯这些点。

可是在网上寻了半天,所有点算法里面,都是请求有一系列按某个时针次序罗列的点。

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

X轴两极点分割

无奈之下只好寻Google,然后就发明了知乎上的一个答案挺好的: 怎样将平面上无序的一组点连成一个简略多边形?

概括算法描述,大家看阿谁答案就好,我就不赘述了。

不外在连贯上链和下链的时候,其实只有保障上链是X轴落序连贯,下链是X轴升序连贯即可(以逆时针标的目的绘制)。至于X轴雷同的点,无论是优先Y轴大的还是小的都可以。

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

在推断一个点是属于上链还是下链的时候,一开端想的是基于两点肯定直线的函数方程,再引入点的坐标来盘算。不外背面想到,所有的点都以最左边的极点来盘算歪角,然后依据角度大小来划分,视觉上更好了解。

大致代码如下:

let balls = [];
let tempBalls = [];
let ballNum = 6;
let isDragingBall = false;

while(ballNum--) {
  let ball = new Ball(10, parseColor(Math.random() * 0xffffff))
  ball.x = Math.random() * width;
  ball.y = Math.random() * height;
  tempBalls.push(ball)
}

// 让点按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 false
  }
  let angle = Math.atan2(ball.y - firstBall.y, ball.x - firstBall.x);
  if (angle > splitLineAngle) {
    lowerBalls.push(ball)
  } else {
    upperBalls.push(ball)
  }
})

// 处置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) => {
  if (ballA.x !== ballB.x) {
    return ballB.x - ballA.x
  }
  return ballB.y - ballB.x
})

// 逆时针连贯所有的点
balls = [firstBall].concat(lowerBalls, [lastBall], upperBalls)

balls = balls.map((ball, i) => {
  ball.text = i + 1;
  return ball
})

终究返回的balls,就是按逆时针排序的多边形的点了。

结果如下:

以上就是本文的全部内容,但愿对大家的学习有所帮忙,更多相干内容请关注百分百源码网!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有150人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板