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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在HTML5中绘制多个随机并确保它们不重叠,可以采用以下步骤: 1. 首先,定义一个的类,包含心坐标(x,y)和半径(radius)属性,以及draw()方法来绘制。 2. 创建一个数组来存储所有的对象。 3. 使用一个循环来生成随机,每次循环生成一个并检查它是否与之前生成的重叠。如果重叠,则重新生成。 4. 生成一个随机心坐标和半径,然后检查它是否与数组中已有的重叠。可以使用勾股定理来计算心之间的距离,如果距离小于两个半径之和,则认为它们重叠了。 5. 如果重叠,则将它添加到数组中,并调用它的draw()方法来绘制它。 以下是一个基本的实现示例: ```html <!DOCTYPE html> <html> <head> <title>随机</title> <style> canvas { border: 1px solid black; } </style> </head> <body> <canvas id="myCanvas" width="500" height="500"></canvas> <script> var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); // 定义类 function Circle(x, y, r) { this.x = x; this.y = y; this.r = r; this.draw = function() { ctx.beginPath(); ctx.arc(this.x, this.y, this.r, 0, 2*Math.PI); ctx.stroke(); } } var circles = []; // 生成随机 function generateCircles(num) { for (var i = 0; i < num; i++) { var x = Math.random() * canvas.width; var y = Math.random() * canvas.height; var r = Math.random() * 50 + 10; var circle = new Circle(x, y, r); // 检查是否重叠 var overlap = false; for (var j = 0; j < circles.length; j++) { var distance = Math.sqrt(Math.pow(circles[j].x - x, 2) + Math.pow(circles[j].y - y, 2)); if (distance < circles[j].r + r) { overlap = true; break; } } // 如果重叠,则添加到数组中并绘制它 if (!overlap) { circles.push(circle); circle.draw(); } else { i--; } } } generateCircles(10); </script> </body> </html> ``` 在上面的示例中,我们生成了10个随机,并使用数组来存储它们。每次生成一个新时,我们都会检查它是否与数组中已有的重叠,如果重叠,则重新生成。最后,我们调用每个的draw()方法来在canvas上绘制它们。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值