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

本文实例为大家分享了js实现固定区域内的不重叠随机圆,供大家参考,具体内容如下

关键词: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" style="border:1px solid #d3d3d3;">
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>

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

(0)

相关推荐

  • JS实现随机乱撞彩色圆球特效的方法

    本文实例讲述了JS实现随机乱撞彩色圆球特效的方法.分享给大家供大家参考.具体实现方法如下: <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JS实现的随机乱撞的彩色圆球特效代码</title> <style> body{ font-family: 微软雅黑; } body,h1{ margin

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

    本文实例为大家分享了js实现固定区域内的不重叠随机圆,供大家参考,具体内容如下 关键词:js.固定区域.不重叠.随机圆,半径固定.半径随机 最近公司有一个需求就是在一个固定的区域(500X500)内显示10个圆,且半径固定,而且不重叠 因为圆的个数固定,而且半径固定,那么就有可能会没有解决方案. 不过其实也没有很难,处理好半径的最大值就好了. 效果图: 思路: (固定半径) step1:先在区域内生成一个随机的圆心坐标, step2:然后拿一个固定半径(从大到小拿固定半径) step3:判断圆心

  • JS实现超精简的链接列表在固定区域内滚动效果代码

    本文实例讲述了JS实现超精简的链接列表在固定区域内滚动效果代码.分享给大家供大家参考,具体如下: 这款超精简版的链接列表文字滚动代码,可在指定的区域内滚动,当然,区域大小可以自己设置的. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-link-list-scroll-style-codes/ 具体代码如下: <html> <HEAD> <TITLE>文字链接列表滚动</TITLE> <META

  • js实现固定显示区域内自动缩放图片的方法

    本文实例讲述了js实现固定显示区域内自动缩放图片的方法.分享给大家供大家参考.具体实现方法如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">

  • 基于jquery的一个拖拽到指定区域内的效果

    这个可与前两个不同了,这个是拖拽到指定的区域内的特效.其实逻辑方式差不多,只不过不同的是 找到目标元素,用appendTo 的方法插入到目标元素. 具体的代码如下,有兴趣者可以试下.(由于是初学,做的简单,如果有其他的方法请给下指点,我定感激不尽哈...) 复制代码 代码如下: <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/htm

  • 利用mongodb查询某坐标是否在规定多边形区域内的方法

    前言 大家都知道MongoDB是一个基于分布式文件存储的数据库,并提供创建基于地理空间的索引的能力,本文将使用MongoDB 基于地理空间索引进行坐标所在区域的判断及使用. 1.使用百度拾取坐标工具,在地图上定义多边形的坐标点,并把每个点的坐标保存. 百度拾取坐标工具:http://api.map.baidu.com/lbsapi/getpoint/ 多边形的坐标点如下: 113.314882,23.163055 113.355845,23.167042 113.370289,23.149564

  • javascript 指定区域内图片等比例缩放实现代码 脚本之家整合版 原创

    我们整合篇,欢迎转载. 复制代码 代码如下: function controlImg(ele,w,h){ var c=ele.getElementsByTagName("img"); for(var i=0;i<c.length;i++){ var w0=c[i].clientWidth,h0=c[i].clientHeight; var t1=w0/w,t2=h0/h; if(t1>1||t2>1){ c[i].width=Math.floor(w0/(t1>

  • js实现限定区域范围拖拉拽效果

    本文实例为大家分享了js实现限定区域范围拖拉拽的具体代码,供大家参考,具体内容如下 需要在范围内拖拉拽,之前看来许多资料觉得都不是特别满足要求,今天自己写了一个,通过监听鼠标按下.鼠标抬起.鼠标移动事件来控制 代码如下 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" c

  • php+mongodb判断坐标是否在指定多边形区域内的实例

    MongoDB是一个基于分布式文件存储的数据库,并提供创建基于地理空间的索引的能力,本文将提供使用PHP连接mongodb,判断坐标是否在指定多边形区域内的实例. 1.定义多边形区域 多边形的坐标点如下: 113.314882,23.163055 113.355845,23.167042 113.370289,23.149564 113.356779,23.129758 113.338238,23.13913 113.330979,23.124706 113.313588,23.140858 1

  • JS实现控制表格内指定单元格内容对齐的方法

    本文实例讲述了JS实现控制表格内指定单元格内容对齐的方法.分享给大家供大家参考.具体如下: 下面的代码控制表格单元格的内容向右对齐 <!DOCTYPE html> <html> <head> <script> function alignCell() { document.getElementById('td1').align="right"; } </script> </head> <body> &l

  • JS实现固定在右下角可展开收缩DIV层的方法

    本文实例讲述了JS实现固定在右下角可展开收缩DIV层的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"

随机推荐