canvas 畫不重疊的圓,

1. 前言

     使用canvas在一個矩形內畫不重複的圓,須要注意兩點javascript

  1. 使用隨機數(Math.random())生成的座標、半徑和寬高比較
  2. 求出兩個圓心的距離

2. html代碼

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            background: #efefef;
        }

        .box {
            width: 500px;
            height: 500px;
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            margin: auto;
            border: 1px solid #999;
        }
    </style>
</head>

<body>
    <div class="box" id="box"></div>
</body>
<script src="./jquery.min.js"></script>
<script src="./circleDraw.js"></script>
<script>
    $('#box').draw({
        number: 50, // 圓的個數
        colors: ['#FF8E56', '#00A0FF', '#0ADFCD', '#1678D3', '#00D069', '#ECB700'],
        text: ['Chrome', '火狐', 'Opera', '360', '獵豹', 'safari']
    });
</script>

</html>

3. circleDraw.js

(function ($) {
    $.fn.extend({
        draw: function (option) {
            if (!option) {
                option = {};
            }
            option = $.extend({}, $.fn.draw.defaultOption, option);
            try{
                if(!(option.colors instanceof Array) || !(option.text instanceof Array)){
                  throw Error('colors、text 接受的參數是 Array[string]');
                }
            }catch(e){
                console.log(e.stack)
            }
            var that = $(this);
            try{
                var width = $(that).width(),
                height = $(that).height();
                if(!(width && height)){
                  throw Error('請設置寬高度');
                }
            }catch(e){
                console.log(e.stack)
            }
            $(that).append("<canvas width="+width+" height="+height+"></canvas>");
            var obj = $(that).find('canvas')[0];
            ctx = obj.getContext('2d');
            var circularIndex = 0,
                loopIndex = 0;
            // 獲取中心點的座標和半徑 x1 , y1 , r1;
            try{
                while (true) {
                    circularIndex++;
                    // 尋找0 - ?  之間的數值
                    var x = Math.floor(Math.random() * width),
                        y = Math.floor(Math.random() * height);
                    var cir = $.fn.draw.circular.effect(x , y , width , height);
                    if(!cir){
                        circularIndex --;
                        loopIndex++;
                        if(loopIndex > 500000){ // 若是循環4000+ 尚未找到合適的圓,中止,防止死循環
                            break;
                        }
                        continue;
                    }else{
                        var color = option.colors[circularIndex] ? option.colors[circularIndex] : 
                                option.colors[circularIndex % option.colors.length ];
                        var text = option.text[circularIndex] ? option.text[circularIndex] : 
                        option.text[circularIndex % option.text.length ];
                        $.fn.draw.circular.begin(cir.x , cir.y , cir.r , text , color ,ctx);
                    }
                    if (circularIndex >=option.number) { // 隨機生成10個園
                        break;
                    }
                }
            }catch(e){
                console.log(e);
            }
        }
    });
})(jQuery);
(function ($) {
    var recordArr = [];
    $.fn.draw.defaultOption = {
        number:5, // 生成的個數
        colors: ['#FF8E56'], // 默認一個顏色,能夠接受的參數是 Array
        text:['Chrome']
    }
    $.fn.draw.circular = {
        /**
          x1  x軸座標
          y   y軸座標
          r   半徑
          text 文字
          color 填充顏色
        **/
        begin: function (x, y, r, text, color , ctx) {
            recordArr.push({
                x: x,
                y: y,
                r: r
            })
            ctx.beginPath();
            ctx.arc(x, y, r, 0, 2 * Math.PI, false);
            ctx.fillStyle = color;
            ctx.fill();
            ctx.font = "14px Microsoft YaHei";
            ctx.fillStyle = "#fffffe";
            ctx.textAlign = "center";
            ctx.fillText(text, x , y + 5);
            ctx.closePath();
        },
        /**
         * x 座標
         * y 座標
         * width 當前盒子寬度
         * height 盒子高度
         *  */
        effect:function (x , y , width , height) { 
            // 設置一個以盒子大小來計算的半徑
            var boxR = Math.floor(width / 6);
            // 獲取隨機半徑
            var randomR = Math.floor(Math.random() * boxR);
            if (randomR < 30) { // 設置半徑不能低於30
               return false;
            } else {
                // 不能劃到框外
                if (x + randomR > width || y + randomR > height) {
                    return false;
                } else if (y - 2 * randomR < 0 || x - 2 * randomR < 0) {
                    return false;
                }
                // 不能出現重疊圓
                for(var a = 0 ; a < recordArr.length ; a++){
                    var distant = Math.floor(Math.sqrt(
                        Math.pow(Math.abs(recordArr[a].x - x), 2) + Math.pow(Math.abs(recordArr[a].y - y), 2)
                    ));
                    if(distant < randomR + recordArr[a].r){
                        return false;
                    }
                }
                return {
                    x:x,
                    y:y,
                    r:randomR
                };
            }
        }
    }
})(jQuery)

歡迎你們吐槽,若是轉載請標明出處。

相關文章
相關標籤/搜索