欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue使用Canvas生成随机大小且不重叠圆

程序员文章站 2022-03-13 10:53:23
目录canvas 相关文档效果图展示案例完整代码父组件代码子组件代码总结canvas 相关文档 canvas api canvas速查简表效果图展示第一张是 随机颜色随机大小聚合 在一起效...

canvas 相关文档

效果图展示

第一张是 随机颜色随机大小聚合 在一起效果

Vue使用Canvas生成随机大小且不重叠圆

第二张是 随机背景图片随机大小分散 效果(这里我使用的图片都一样所以没展现出不同图片)

Vue使用Canvas生成随机大小且不重叠圆

案例完整代码

  • 本实例是用 vue 来实现的,其他方法和 vue 类似,改为对应的语法即可实现效果。
  • 案例用到了 vue 父子组件传值

父组件代码

<template>
  <div id="home">
      <div class="tags" ref="tags">
        <circle-box :parentclientwidth="parentclientwidth" :parentclientheight="parentclientheight" :datalist="datalist"></circle-box>
      </div>
  </div>
</template>
<script>
import circlebox from '@/components/content/circle/circle.vue'
export default {
  components: { circlebox },
  data() {
    return {
      parentclientwidth: 0,
      parentclientheight: 0,
      // canvas 模拟数据
      datalist: [
       {
          follow: 1,
          image: 'http://39.99.139.115/demo/rb5.png'
        },
        {
          follow: 2,
          image: 'http://39.99.139.115/demo/rb5.png'
        },
        {
          follow: 3,
          image: 'http://39.99.139.115/demo/rb5.png'
        },
        {
          follow: 4,
          image: 'http://39.99.139.115/demo/rb5.png'
        },
        {
          follow: 5,
          image: 'http://39.99.139.115/demo/rb5.png'
        },
        {
          follow: 6,
          image: 'http://39.99.139.115/demo/rb5.png'
        },
        {
          follow: 7,
          image: 'http://39.99.139.115/demo/rb5.png'
        },
        {
          follow: 8,
          image: 'http://39.99.139.115/demo/rb5.png'
        },
        {
          follow: 9,
          image: 'http://39.99.139.115/demo/rb5.png'
        },
        {
          follow: 10,
          image: 'http://39.99.139.115/demo/rb5.png'
        }
      ],
    };
  },
  
  created() {},
  
  mounted() {
    this.getwidth();
  },
  
  methods: {
    // 获取父盒子的宽度和高度
    getwidth() {
      this.parentclientwidth = this.$refs.tags.clientwidth;
      this.parentclientheight = this.$refs.tags.clientheight;
      console.log(this.$refs.tags.clientwidth);
    }
  },
};
</script>

子组件代码

<template>
  <div>
    <canvas id="mycanvas" :width="parentclientwidth + 'px'" :height="parentclientheight + 'px'"></canvas>
  </div>
</template>
<script>
export default {
  // 接收数据
  props: ['parentclientwidth', 'parentclientheight', 'datalist'],

  data() {
    return {
      datalistcopy: this.datalist
    }
  },
  
  created() {
    this.$nexttick(() => {
      // 初始化
      this.circleinfo()
    })
  },
  
  mounted() {},
  
  methods: {
    circleinfo() {
      let that = this
      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)
          console.log(this.c)

          this.ctx = this.c.getcontext('2d')
          this.dwidth = this.c.width
          this.dheight = this.c.height
          this.fix = obj.fix || true

          this.minmargin = obj.minmargin || 20
          this.minradius = obj.minradius || 30
          this.radiuarr = obj.radiuarr || [30, 30, 30, 30, 30, 30, 30, 30, 30, 30]

          this.total = obj.total || 10

          this.circlearray = []
          this.circlenumber = 1
        }

        drawonecircle(c, index) {
          // console.log(c, index)
          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.textalign = 'center'
          // ctx.textbaseline = 'middle'

          // ctx.fillstyle = 'black'
          // ctx.font = '1rem 微软雅黑'
          // ctx.filltext(that.datalistcopy[index].follow, c.x, c.y - 10) //圆内文字

          let img = new image()
          img.src = that.datalistcopy[index].image
          ctx.drawimage(img, c.x - c.r, c.y - c.r, c.r * 2, c.r * 2)

          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 + 20)

          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, index) => {
              this.drawonecircle(c, index)
            })
        }
      }
      // console.log(this.circle);

      const p = new randomcircle({
        id: 'mycanvas',
        total: that.datalistcopy.length // 配置数量
      })

      p.init()
      console.log(p)
      console.log(p.circlearray)
    }
  }
}
</script>

总结

到此这篇关于vue使用canvas生成随机大小且不重叠圆的文章就介绍到这了,更多相关vue用canvas生成随机圆内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!