做一个在屏幕上随机分布泡泡的功能

我心飞翔 分类:javascript

最近工作上要做一个功能,就是要在一个平面上随机分布几个大小不一的泡泡,泡泡不能相互覆盖或者只能覆盖小部分。后面泡泡之间会有关系链,其它所有泡泡围着一个泡泡的关系,大概需求就是这样。

需要达到的效果:

r2.gif

开始吧

这里用的小程序里的movable-view,这个只要设置X,Y和宽高就会有一个不错的效果。

// 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>
 
// 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;
}
 
// pages/random/random.js
Page({

  data: {
    // x ,y 是图形左上角距离屏幕左上角的px
    list:[]
  },
  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++){
      // 先把宽高随机出来,因为x ,y 是泡泡左上角距离屏幕左上角的px,所以实际随机的范围要减去这个宽高
      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
    })
  }
})
 

这些就可以实现初版效果了。
r1.gif

怎样让它们之间不覆盖呢

我的思路是这样的:每随机一个圆的时候,判断这个圆与之前的所有圆是否互相覆盖,如果互相覆盖,就重新随机。(看起来就很暴力 doge,先做出来之后再优化)

那怎样判断它们互相覆盖呢,其实只有两种情况

  • 圆的边相交 (圆心到圆心的距离小于两个圆半径之和)
  • 一个圆在另一个圆的肚子里面 (圆心到圆心的距离小于两个圆半径之和)
// 两个圆的圆心
let centerOfCircle = {
    x: x+wh/2,
    y: y+wh/2,
}
let preCenterOfCircle = {
    x: perX+wh/2,
    y: preY+wh/2,
}

// 判断方法
let centerOfCircleDistance = this.getDistance(centerOfCircle,preCenterOfCircle)
let longerWh = wh>preWh?wh:preWh
if(centerOfCircleDistance < (wh/2+preWh/2) || centerOfCircleDistance<longerWh){
    // 这是相交了,就重新随机再判断
}
      
// 计算两个点之间的距离
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;
}

 

那可以开始创建泡泡啦

贴上全部代码

// pages/random/random.js
Page({

  data: {
    // x ,y 是图形左上角距离屏幕左上角的px
    list:[]
  },
  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.randomNum(0,this.data.windowWidth - wh)
    let y = 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.log(perX,preY,preWh)
      // 判断有没有相交主要是判断:两个圆心之间的距离有没有大于他们半径之和
      let centerOfCircle = {
        x: x+wh/2,
        y: y+wh/2,
      }
      let preCenterOfCircle = {
        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){
        // 这是相交了,就重新随机再判断
        console.log('香蕉了',i,j)
        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;
  }
})
 

之后再看看怎么优化一下。。。

回复

我来回复
  • 暂无回复内容