【问题标题】:create random rectangles with random colors without overlapping using javascript使用javascript创建具有随机颜色而不重叠的随机矩形
【发布时间】:2020-10-12 08:48:55
【问题描述】:

如何使用 javascript 在 HTML 中创建类似的内容?

实际上,我知道如何在 HTML 中创建矩形,但想做这样的事情。 HTML 画布可以是任何大小,但每当加载页面时,都会生成多个具有随机大小和颜色的正方形,而不会重叠。当我尝试这样做时,矩形以列表形式生成。我是一名网络开发人员(面向 ruby​​ on rails),但对此类 javascript 内容不熟悉。任何帮助将不胜感激。

html:

<body>
    <div id="randBlock" >
    </div>
</body>

javascript:

(function makeDiv(){
    var divsize = ((Math.random()*100) + 50).toFixed();
    var color = '#'+ Math.round(0xffffff * Math.random()).toString(16);
    $newdiv = $('#randBlock').css({
        'width':divsize+'px',
        'height':divsize+'px',
        'background-color': color
    });

    var posx = (Math.random() * ($(document).width() - divsize)).toFixed();
    var posy = (Math.random() * ($(document).height() - divsize)).toFixed();

    $newdiv.css({
        'position':'absolute',
        'left':posx+'px',
        'top':posy+'px',
        'display':'none'
    }).appendTo( 'body' ).fadeIn(100).delay(300).fadeOut(200, function(){
       $(this).remove();
       makeDiv(); 
    }); 
})();

【问题讨论】:

  • @Paulie_D 问题非常具体。每当页面加载时,都会创建一个宽度等于屏幕的 div。这个 div 需要包含图像中的块,这些块以随机颜色随机定位但不相互重叠。我是一名 ruby​​ on rails 开发人员,对这种 javascript 编码的经验较少。任何帮助将不胜感激。
  • @Paulie_D 我很抱歉我没有分享代码。
  • OK...已投票重新开放。
  • 您是否需要特定数量的方格?你想要什么淡入/淡出?所有的方块都在一起,还是依次消失?要求不重叠会给您的算法增加很多复杂性;要求严格吗?
  • @ScottMermelstein Number 不需要超过 10 个。所有的块都需要出现和消失。事实上,现在在代码中它们会自动出现和消失,它们需要是静态的,因为我会将随机化的东西分配给一个按钮。但是,是的,它不需要重叠。

标签: javascript html css canvas


【解决方案1】:

使用画布的解决方案(所以我理解这个问题)。

内置碰撞检测isInside()

编辑:更好的随机支持,不会永远运行,来自Drawing a 1px thick line in canvas creates a 2px thick line 的提示和来自这个答案Random Color generator in Javascript 的一点点

function getRandomColor() {
    var color = '#';
    for (var i = 0; i < 6; i++) {
        color += (Math.random() * 16 | 0).toString(16);
    }
    return color;
}

function Point(x, y) {
    this.x = x;
    this.y = y;
}

function Rectangle(p1, p2) {
    this.p1 = p1;
    this.p2 = p2;
}

Rectangle.prototype.isInside = function (r) {
    function check(a, b) {
        return (
            a.p1.x <= b.p1.x && b.p1.x <= a.p2.x && a.p1.y <= b.p1.y && b.p1.y <= a.p2.y ||
            a.p1.x <= b.p2.x && b.p2.x <= a.p2.x && a.p1.y <= b.p2.y && b.p2.y <= a.p2.y ||
            a.p1.x <= b.p2.x && b.p2.x <= a.p2.x && a.p1.y <= b.p1.y && b.p1.y <= a.p2.y ||
            a.p1.x <= b.p1.x && b.p1.x <= a.p2.x && a.p1.y <= b.p2.y && b.p2.y <= a.p2.y
        );
    }
    return check(this, r) || check(r, this);
}

function generateRectangles() {
    function p() { return Math.random() * 300 | 0; }
    function s() { return 50 + Math.random() * 150 | 0; }

    var rectangles = [],
        r, size, x, y, isInside, i, counter = 0;

    for (i = 0; i < 20; i++) {
        counter = 0;
        do {
            counter++;
            x = p();
            y = p();
            size = s();
            r = new Rectangle(new Point(x, y), new Point(x + size, y + size));
            isInside = rectangles.some(function (a) {
                return a.isInside(r);
            });
        } while (isInside && counter < 1000);
        counter < 1000 && rectangles.push(r);
    }
    return rectangles;
}

function drawRectangles(rectangles) {
    var canvas = document.getElementById("canvas"),
        ctx = canvas.getContext("2d");

    rectangles.forEach(function (a) {
        ctx.lineWidth = 1;
        ctx.strokeRect(a.p1.x + 0.5, a.p1.y + 0.5, a.p2.x - a.p1.x - 1, a.p2.y - a.p1.y - 1);
        ctx.fillStyle = getRandomColor();
        ctx.fillRect(a.p1.x + 0.5, a.p1.y + 0.5, a.p2.x - a.p1.x - 1, a.p2.y - a.p1.y - 1);
    });
}

var rectangles = generateRectangles();
drawRectangles(rectangles);
&lt;canvas id="canvas" width="500" height="500"&gt;&lt;/canvas&gt;

【讨论】:

  • 谢谢!这正是我所要求的。 :)
  • 我本可以引入一个错误,但我几乎可以肯定,当边界对齐时,您会遇到边缘情况(双关语)。我看到的是内部方块jsfiddle.net/Victornpb/3hc0j5pd
  • 这里是 s/o,我没有看到重叠...
【解决方案2】:

你已经让它绘制了一个随机位置的随机正方形。从那里开始绘制很多很容易——只需有一个循环来添加多个 div。当然,然后你需要给每个人一个随机的 id,但这很容易。问题是这将允许重叠。

最简单的情况:允许重叠

function makeDiv(i) {
  var divsize = ((Math.random() * 100) + 50).toFixed();
  var color = '#' + Math.round(0xffffff * Math.random()).toString(16);
  var posx = (Math.random() * ($(document).width() - divsize)).toFixed();
  var posy = (Math.random() * ($(document).height() - divsize)).toFixed();
  var divid = 'randBlock' + i;

  $('#randBlock').append("<div id='" + divid + "'>");
  $('#' + divid).css({
    'width': divsize + 'px',
    'height': divsize + 'px',
    'background-color': color,
    'position': 'absolute',
    'left': posx + 'px',
    'top': posy + 'px'
  });
}

for (var i = 0; i < 10; ++i) {
  makeDiv(i);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
  <div id="randBlock">
  </div>
</body>

如果你想保证它不重叠,你还有很多工作要做,除非你可以做一些 CSS 魔法,这是很有可能的,但我不知道。您必须跟踪每个正方形的位置和大小,并且只将结果放入清晰的区域。

根据您的具体要求,您的算法会有所不同。您将不得不有一些限制 - 无论是正方形的最大尺寸,重叠的要求,您想要适应的最大正方形数量,还是允许正方形变得越来越小。我将为您提供其中两个的口头演练。网格想法有一个有效的 sn-p。根据您在 cmets 中添加的内容,这可能就足够了。

您已经构建了一个固定大小,所以最好的办法是使用该大小作为基础,并创建一个网格。在这种情况下,您会知道每个 gridsquare 中可以有一个正方形。有一个存储每个 gridsquare 位置的数组,并从(1 到该数组的长度)中随机选择 - 1。在该 gridsquare 中,适合一个正方形,与您当前拥有的功能非常相似。它的大小是您已经设置的最大值,并且它在该框中的位置可以根据大小随机。

网格案例

var fixedScale = 100;
var fixedConstant = 50;
var fixedMax = fixedScale + fixedConstant;
var gridCols = (($(document).width() / fixedMax) + 1).toFixed();
var gridRows = (($(document).height() / fixedMax) + 1).toFixed();
var grid = [];
for (var row = 0; row < gridRows; ++row) {
  for (var col = 0; col < gridCols; ++col) {
    var index = row * gridCols + col;
    grid[index] = {row: row, col: col};
  }
}

function makeDiv(i) {
  var gridId = Math.floor(Math.random() * grid.length);
  
  var divsize = ((Math.random() * fixedScale) + fixedConstant).toFixed();
  console.log(gridId + ", grid.length = " + grid.length);
  var color = '#' + Math.round(0xffffff * Math.random()).toString(16);
  var posx = grid[gridId].col * fixedMax;
  var posy = grid[gridId].row * fixedMax;
  var offsetx = (Math.random() * (fixedMax - divsize)).toFixed();
  var offsety = (Math.random() * (fixedMax - divsize)).toFixed();
  posx = +posx + +offsetx;
  posy = +posy + +offsety;
  var divid = 'randBlock' + i;

  grid.splice(gridId, 1);
  
  $('#randBlock').append("<div id='" + divid + "'>");
  $('#' + divid).css({
    'width': divsize + 'px',
    'height': divsize + 'px',
    'background-color': color,
    'position': 'absolute',
    'left': posx + 'px',
    'top': posy + 'px'
  });
}

for (var i = 0; i < 10; ++i) {
  makeDiv(i);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
  <div id="randBlock">
  </div>
</body>

使用以下事实,您可以拥有无​​限的(但递减的正方形):任何时候将正方形添加到空白区域中,都会在该区域中留下四个剩余空间的矩形。任何时候你制作一个彩色方块,你实际上可以制作 5 个 div:彩色方块、顶部的空白区域、右侧、底部和左侧。将空的归于特定的类。然后,查看所有具有“空”类的 div,并将您的最大大小设置为空 div 的最大值。创建下一个彩色方块时,随机选择一个至少与方块一样大的 div。

显然,这些代码并不完全是微不足道的。您在要求和约束中所做的选择将对您的编码工作产生巨大影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 2019-01-31
    • 2022-07-06
    • 1970-01-01
    • 2022-01-03
    相关资源
    最近更新 更多