新西兰服务器

js怎么实现固定区域内的不重叠随机圆


js怎么实现固定区域内的不重叠随机圆

发布时间:2021-04-19 11:29:51 来源:高防服务器网 阅读:145 作者:小新 栏目:web开发

这篇文章给大家分享的是有关js怎么实现固定区域内的不重叠随机圆的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

最近公司有一个需求就是在一个固定的区域(500X500)内显示10个圆,且半径固定,而且不重叠

因为圆的个数固定,而且半径固定,那么就有可能会没有解决方案。

不过其实也没有很难,处理好半径的最大值就好了。

效果图:

思路:

(固定半径)

step1:先在区域内生成一个随机的圆心坐标,
step2:然后拿一个固定半径(从大到小拿固定半径)
step3:判断圆心和半径是否合法(是否超边距,或者两个圆相交)
step4:如果不合法,重新执行step2和step3
step5:如果合法,记为一个新圆
step6:重复step1~5,直到生成10个圆

(随机半径)

step1:先在区域内生成一个随机的圆心坐标,
step2:根据圆心坐标,与其他圆比较,获取最短的圆心距减去比较圆的半径(圆心距-R n  RnR_n)的值,作为新圆的半径(这样就会生成一个相切的圆)
step3:判断圆心和半径是否合法(是否超边距)
step4:如果不合法,重新执行step2和step3
step5:如果合法,记为一个新圆
step6:重复step1~5,直到生成10个圆

代码:

// 参数  let obj = {    id: string, // canvas 的id    fix:boolean, // 是否固定半径,默认为false    minMargin: Number, // 两个圆的最短距离,默认为10    minRadius: Number, 最小的圆半径,默认为30    radiuArr: Array, 圆的半径的数组,当fix为true时该值必须填    total: Number ,圆的个数,默认为10  }
<!DOCTYPE html>  <html>  <body>    <canvas id="myCanvas" width="500" height="500" >  Your browser does not support the HTML5 canvas tag.  </canvas>    <script>  class Circle {    constructor(x, y, r, color){      this.x = x      this.y = y      this.r = r,      this.c = color ? color : this.getRandomColor()    }    getRandomColor(){       let r = Math.floor(Math.random()*100) + 155      let g = Math.floor(Math.random()*100) + 155      let b = Math.floor(Math.random()*100) + 155      return `rgb(${r},${g},${b})`     }   }    class RandomCircle {      constructor(obj) {      this.c      = document.getElementById(obj.id);      this.ctx     = this.c.getContext("2d");      this.dWidth   = this.c.width;      this.dHeight   = this.c.height        this.fix     = obj.fix || false;      this.minMargin  = obj.minMargin || 10       this.minRadius  = obj.minRadius || 30      this.radiuArr  = obj.radiuArr || [80,70,60,50,45,40,40,35,35,30]      this.total = obj.total || 10      this.circleArray = []      this.circleNumber = 1    }        drawOneCircle(c) {      let ctx = this.ctx;      ctx.beginPath();      ctx.strokeStyle = c.c;      ctx.fillStyle=c.c;      ctx.arc(c.x, c.y, c.r, 0, 2*Math.PI);      ctx.stroke();      ctx.fill();        ctx.fillStyle='black';      ctx.fillText('No:'+this.circleNumber, c.x-10, c.y-5);      ctx.fillText('R:'+c.r, c.x-10, c.y+5);      this.circleNumber ++     }      check(x,y,r) {      return !(x+r > this.dWidth || x-r < 0 || y + r > this.dHeight || y-r < 0)    }      // 获取一个新圆的半径,主要判断半径与最近的一个圆的距离    getR(x,y) {      if (this.circleArray.length === 0) return Math.floor(Math.random()*20 + 80)      let lenArr = this.circleArray.map(c => {        let xSpan = c.x-x        let ySpan = c.y-y        return Math.floor(Math.sqrt(Math.pow(xSpan,2) + Math.pow(ySpan,2))) - c.r      })      let minCircleLen = Math.min(...lenArr)      let minC = this.circleArray[lenArr.indexOf(minCircleLen)]      let tempR = this.fix ? this.radiuArr[this.circleArray.length] : minCircleLen - this.minMargin      let bool = this.fix ? (tempR <= minCircleLen - minC.r) : (tempR >= this.minRadius)      return bool ? tempR : false    }      // 生成一个圆,随机生成圆心。    // 如果连续生成200次半径都没有合适的话,终止进程    createOneCircle(){      let x,y,r;      let createCircleTimes = 0      while(true) {        createCircleTimes ++         x = Math.floor(Math.random()*this.dWidth)        y = Math.floor(Math.random()*this.dHeight)        let TR = this.getR(x,y)        if (!TR) {          continue;        } else {          r = TR        }        if (this.check(x,y,r) || createCircleTimes > 200) {          break        }        }      this.check(x,y,r) && this.circleArray.push(new Circle(x, y, r))      }      // 如果生成100次新圆都失败的话,终止方案。    // 如果生成100种方案都没有合适可用的话,终止进程。    init() {      let n = 0      while(this.circleArray.length < this.total) {        this.circleArray = []        let i = 0;        while (this.circleArray.length < this.total) {          this.createOneCircle()          i ++           if (i >= 100) {            break;          }        }        n ++         if (n > 100) {          break;        }      }      // 根据半径从大到小画圆。      this.circleArray.sort( (a,b) => b.r-a.r).forEach(c => {        this.drawOneCircle(c)      })    }  }      let p = new RandomCircle({id: 'myCanvas', total: 20})  p.init()    console.log(p.circleArray)    </script>   </body>  </html>

感谢各位的阅读!关于“js怎么实现固定区域内的不重叠随机圆”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

[微信提示:高防服务器能助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

[图文来源于网络,不代表本站立场,如有侵权,请联系高防服务器网删除]
[