Recently, I want to make a function in my work, which is to randomly distribute several bubbles of different sizes on a plane. The bubbles can not cover each other or only cover a small part. And then there’s a chain of relationships between the bubbles, and all the other bubbles around one bubble, and that’s what demand looks like.

Effects to be achieved:

Let’s start

Here’s the movable-view widget, which just sets X,Y and width and height to have a great effect.

// wxml <movable-area class="box"> <movable-view wx:for="{{list}}" wx:key="index" direction="all" class="item" x="{{item.x}}" y="{{item.y}}" style="width:{{item.wh}}px; height:{{item.wh}}px;" > {{index}} </movable-view> </movable-area> <button class="btn" bindtap="random">random</button>Copy the code
// wxss
page{
  width: 100%;
  height: 100%;
}
.box{
  width: 100%;
  height: 100%;
}
.item{
  border: 1rpx solid red;
  border-radius: 50%;
  display: flex;
  display: -webkit-flex;
  justify-content: center;
  align-items: center;
}
.btn{
  width: 100%;
  height: 80rpx;
  position: fixed;
  bottom: 0rpx;
  left: 0rpx;
}
Copy the code
// pages/random/random.js Page({data: {x,y = px :[]}, onLoad: function (options) { let {windowHeight,windowWidth} = wx.getSystemInfoSync() this.setData({ windowHeight, // 672 windowWidth, // 414 }) this.random() }, random(){ const randomNum = (min, max) => { let randomNum = Math.floor(Math.random() * (max - min + 1) + min); return randomNum } let list = [] for(let i=0; i<5; I++){// random out the width and height, because x and y are px from the top left corner of the bubble to the top left corner of the screen, Let wh = randomNum(50,200) let obj = {x:randomNum(0, this.data.windowwidth-wh), y:randomNum(0,this.data.windowHeight - wh), wh, } list.push(obj) } this.setData({ list }) } })Copy the code

This will do for the first version.

How do they not cover each other

My idea is this: every time I randomly select a circle, I determine whether it covers all the previous circles, and if it does, I re-random it. (Looks very violent doge, make it first and then optimize it later)

So how do you tell if they cover each other, there are only two cases

  • The sides of a circle meet (the distance from the center to the center is less than the sum of the radii of the two circles)
  • One circle is inside the belly of another circle (the distance from center to center is less than the sum of the radii of the two circles)
Wh /2 = {x: x+wh/2, y: y+wh/2,} preY+wh/2, } / / judgment method let centerOfCircleDistance = this. GetDistance (centerOfCircle preCenterOfCircle) let longerWh wh = > preWh? Wh: preWh if (centerOfCircleDistance < (wh / 2 + preWh / 2) | | centerOfCircleDistance < longerWh) {/ / this is the intersection, } // calculate the distance between two points getDistance(circle1, circle2){let a = circle1.x-circle2.x; let b = circle1.y - circle2.y; let c = Math.sqrt(a * a + b * b); return c; }Copy the code

So you can start creating bubbles

Paste the entire code

// pages/random/random.js Page({data: {x,y = px :[]}, onLoad: function (options) { let {windowHeight,windowWidth} = wx.getSystemInfoSync() this.setData({ windowHeight, // 672 windowWidth, // 414 }) this.random() }, random(){ let list = [] for(let i=0; i<10; i++){ let {x,y,wh} = this.createBubble(list,i) // console.log(`x=${x},y=${y}`) let obj = { x, y, wh, } list.push(obj) } this.setData({ list }) }, CreateBubble (list, I){let wh = this.randomnum (50,200) let x = this.data.windowwidth -wh) let y = this.randomnum (0, this.data.windowwidth -wh this.randomNum(0,this.data.windowHeight - wh) if(list.length == 0){ return {x,y,wh} } for(let j=0; j<list.length; J ++){let {x:perX,y:preY,wh:preWh} = list[j] // console. Let centerOfCircle = {x: x+wh/2, y: y+wh/2,} let preCenterOfCircle = {x: perX+wh/2, y: {x: perX+wh/2, y: {x: perX+wh/2, y: preY+wh/2, } let centerOfCircleDistance = this.getDistance(centerOfCircle,preCenterOfCircle) console.log(centerOfCircleDistance,wh/2+preWh/2) let longerWh = wh>preWh? Wh: preWh if (centerOfCircleDistance < (wh / 2 + preWh / 2) | | centerOfCircleDistance < longerWh) {/ / this is the intersection, Return this.createBubble(list, I)}} return {x,y,wh}}, randomNum(min, max){ let randomNum = Math.floor(Math.random() * (max - min + 1) + min); return randomNum }, getDistance( circle1, circle2){ let a = circle1.x - circle2.x; let b = circle1.y - circle2.y; let c = Math.sqrt(a * a + b * b); return c; }})Copy the code