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


Posted in Javascript onOctober 24, 2019

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

关键词:js、固定区域、不重叠、随机圆,半径固定、半径随机

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

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

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

效果图:

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

思路:

(固定半径)

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>

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

Javascript 相关文章推荐
基于jquery的loading 加载提示效果实现代码
Sep 01 Javascript
JS中不为人知的五种声明Number的方式简要概述
Feb 22 Javascript
IE8对JS通过属性和数组遍历解析不一样的地方探讨
May 06 Javascript
鼠标选择动态改变网页背景颜色的JS代码
Dec 10 Javascript
jQuery判断数组是否包含了指定的元素
Mar 10 Javascript
JS实现点击上移下移LI行数据的方法
Aug 05 Javascript
js游戏人物上下左右跑步效果代码分享
Aug 28 Javascript
Bootstrap 3的box-sizing样式导致UEditor控件的图片无法正常缩放的解决方案
Sep 15 Javascript
js模态对话框使用方法详解
Feb 16 Javascript
原生JS实现自定义滚动条效果
Oct 27 Javascript
利用ECharts.js画K线图的方法示例
Jan 10 Javascript
vue单页开发父子组件传值思路详解
May 18 Javascript
js实现随机div颜色位置 类似满天星效果
Oct 24 #Javascript
windows实现npm和cnpm安装步骤
Oct 24 #Javascript
JS实现简单随机3D骰子
Oct 24 #Javascript
JS合并两个数组的3种方法详解
Oct 24 #Javascript
js实现简单掷骰子小游戏
Oct 24 #Javascript
js实现GIF图片的分解和合成
Oct 24 #Javascript
js实现掷骰子小游戏
Oct 24 #Javascript
You might like
mayfish 数据入库验证代码
2010/04/30 PHP
PHP Error与Logging函数的深入理解
2013/06/03 PHP
php数组索引的Key加引号和不加引号的区别
2014/08/19 PHP
PHP通过bypass disable functions执行系统命令的方法汇总
2018/05/02 PHP
PHP 实现 JSON 数据的编码和解码操作详解
2020/04/22 PHP
js 新浪的一个图片播放图片轮换效果代码
2008/07/15 Javascript
关于js类的定义
2011/06/28 Javascript
一个JS的日期格式化算法示例
2013/07/31 Javascript
js中函数调用的两种常用方法使用介绍
2014/07/17 Javascript
JS遍历数组及打印数组实例分析
2016/01/21 Javascript
js停止冒泡和阻止浏览器默认行为的简单方法
2016/05/15 Javascript
从零开始学习Node.js系列教程五:服务器监听方法示例
2017/04/13 Javascript
使用OPENLAYERS3实现点选的方法
2020/09/24 Javascript
JavaScript实现拖拽效果
2020/03/16 Javascript
python中的一些类型转换函数小结
2013/02/10 Python
python聊天程序实例代码分享
2013/11/18 Python
python3如何将docx转换成pdf文件
2018/03/23 Python
python实现俄罗斯方块游戏
2020/03/25 Python
10 行 Python 代码教你自动发送短信(不想回复工作邮件妙招)
2018/10/11 Python
运用Python的webbrowser实现定时打开特定网页
2019/02/21 Python
python实现顺时针打印矩阵
2019/03/02 Python
基于Python实现大文件分割和命名脚本过程解析
2019/09/29 Python
python被修饰的函数消失问题解决(基于wraps函数)
2019/11/04 Python
python双向链表原理与实现方法详解
2019/12/03 Python
Python新手如何进行闭包时绑定变量操作
2020/05/29 Python
css3的transform中scale缩放详解
2014/12/08 HTML / CSS
CSS3中的display:grid,网格布局介绍
2019/10/30 HTML / CSS
加拿大廉价机票预订网站:CheapOair.ca
2018/03/04 全球购物
Myprotein瑞士官方网站:运动营养和健身网上商店
2019/09/25 全球购物
超市后勤自我鉴定
2014/01/17 职场文书
初中考试作弊检讨书
2014/02/01 职场文书
气象学专业个人求职信
2014/03/15 职场文书
品质口号大全
2014/06/17 职场文书
党的群众路线教育实践活动个人剖析材料
2014/10/07 职场文书
借条格式范本
2015/05/25 职场文书
天堂的孩子观后感
2015/06/11 职场文书