所有分类
  • 所有分类
  • 后端开发
画多边形技巧大揭秘,让你的作品更优美

画多边形技巧大揭秘,让你的作品更优美

这篇文章主要介绍了canvas里面如何基于随机点绘制一个多边形的方法的相关资料,内容挺不错的,现在分享给大家,也给大家做个参考。然后按照角度从小到大的去连接这些点,这样就能画出一个正常的多边形了。可是如果我有这些点,就已经能绘制多边形了。如

随机点绘制多边形的初始尝试

我开始迷上画多边形了,可是做出来效果不怎么样,总有那么点儿小瑕疵。咱们能否试试把点数调成可变的,这样每个点的膨胀程度就能差不多一样。但是有时候随机选的点会过于集中,这样会让交汇处变得有点乱糟糟。那咱们该怎么办?那就是找个方法让整个画面看起来更舒服,更好看!

优化连线方式:按角度连接点

画多边形技巧大揭秘,让你的作品更优美

咱试试看哈。那杂七杂八的交叉线怎么办?找个稳妥的地方算算每根线跟这地方的角度,然后一口气画个直线就成了。虽然还是有些交叉线在,但是肯定比以前强多了!

尝试优化方案

我用了Math.abs来算正角度。找到了连起来后最小夹角的位置,不过结果不是很理想。总不能老是避开交叉线?还是得找一个实用点儿的办法。

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
})

基于中心点旋转连接

找出多边形的重心很关键!然后根据这些点和重心角度来画线,搞懂就好。但有时候算法要求点要按特定顺序排列,那就稍显麻烦了。

画多边形技巧大揭秘,让你的作品更优美

X轴两极点分割

网上学的画不规则多边形很简单,首先用线把这些点连起来就行了。记住,上链时数值要逐渐变小,下链时得变成大的(顺着或者反方向转都可以)。掌握这样的技巧,你也能轻松画出各种变化的图形!

严格按照算法实现

这个办法超好用!只要找出两点间的极点位置,就知道它们之间夹角大小!然后,就可以轻轻松松判定两点是不是处于同一直线上,或者分别位于不同直线上。这个办法超级直观明了,就算遇到复杂的十字路口问题也能搞定!

代码实现与效果展示

我们给画图软件加个改进算法,顺手儿就把逆时针画多边形那个困扰弄没了。这样之后画出的线更美,也没了谁被谁挡住的问题!

其他优化可能性探讨

别只用那招儿,试试换个排列线条的办法。调整后,图形看起来会更酷炫哒!胆子大点儿,新的尝试可能让你发现更棒的优化途径

结语与展望

搞定Canvas画框真是要有一定的数学和编程水平。看完这篇文章后,以后做项目就能轻松用学到的东西找到更好的画图办法。以后还会分享更多有意思的Canvas作品!

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
})

原文链接:https://www.icz.com/technicalinformation/web/vue2/2024/04/13299.html,转载请注明出处~~~
0

评论0

请先
注意:请收藏好网址www.icz.com,防止失联!站内免费资源持续上传中…!赞助我们
显示验证码
没有账号?注册  忘记密码?