JavaScript automatically arranges child elements within their parent container in a random distribution without any overlapping

I am experimenting with creating a dynamic layout of circles (divs with border-radius) within a container without any overlap.

Check out my progress here - https://jsbin.com/domogivuse/2/edit?html,css,js,output

var sizes = [200, 120, 500, 80, 145];
var max = sizes.reduce(function(a, b) {
    return Math.max(a, b);
});
var min = sizes.reduce(function(a, b) {
    return Math.min(a, b);
});
var percentages = sizes.map(function(x) {
    return ((x - min) * 100) / (max - min);
});
percentages.sort(function(a, b) {
    return b-a;
})
var container = document.getElementById('container');
var width = container.clientWidth;
var height = container.clientHeight;
var area = width * height;
var maxCircleArea = (area / sizes.length);
var pi = Math.PI;
var maxRadius = Math.sqrt(maxCircleArea / pi);
var minRadius = maxRadius * 0.50;
var range = maxRadius - minRadius;
var radii = percentages.map(function(x) {
    return ((x / 100) * range) + minRadius;
});
function getRandomArbitrary(min, max) {
    return Math.random() * (max - min) + min;
}

var coords = [];
radii.forEach(function(e, i) {
    var circle = document.createElement('div');
    var randomTop = getRandomArbitrary(0, height);
    var randomLeft = getRandomArbitrary(0, width);
    var top = randomTop + (e * 2) < height ?
        randomTop :
        randomTop - (e * 2) >= 0 ?
        randomTop - (e * 2) :
        randomTop - e;
    var left = randomLeft + (e * 2) < width ?
        randomLeft :
        randomLeft - (e * 2) >= 0 ?
        randomLeft - (e * 2) :
        randomLeft - e;
    var x = left + e;
    var y = top + e;

    coords.push({x: x, y: y, radius: e});
    circle.className = 'bubble';
    circle.style.width = e * 2 + 'px';
    circle.style.height = e * 2 + 'px';
    circle.style.top = top + 'px';
    circle.style.left = left + 'px';
    circle.innerText = i
    container.appendChild(circle);
});

I've successfully added the circles to the container, but they are overlapping. I'm unsure how to resolve this issue. I attempted using a formula like

(x1 - x2)^2 + (y1 - y2)^2 < (radius1 + radius2)^2
, but it's beyond my expertise.

Any assistance would be greatly appreciated.

Answer №1

The task you are attempting to accomplish is known as "Packing" and poses quite a challenge. There are several potential strategies that could be pursued.

One approach involves randomly distributing the circles (as you are currently doing), but with an added "retry" feature. This means that if a circle ends up overlapping another, a new location is attempted. However, there should also be a limit on the number of retries in case the situation becomes impossible. While this method is relatively straightforward, it does have limitations in terms of packing density, as the chances of overlap increase significantly. This would work best when only about 1/3 of the total area needs to be covered by circles.

Another option is to adjust the positions of previously placed circles as new ones are added. This mimics a physical scenario where existing circles need to make room for new additions. A suggestion is to use a "springy" algorithm, where all circles are initially randomly placed without considering fit, then a loop calculates overlaps and applies forces to push circles apart until they no longer overlap. This approach allows for denser configurations, as circles may end up touching each other in the final layout. It will require more complexity in programming, but can handle more intricate arrangements. However, a check for impossibility is still recommended to prevent endless looping.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using scale transformations to animate SVG group elements

I am currently experimenting with an SVG example where I hover over specific elements to expand or scale them. However, I seem to have made a mistake somewhere or missed something important. Can someone offer me assistance? View the demo on JSFiddle here ...

Guide on creating uniform heights and widths for images with varying dimensions utilizing CSS (and percentage values)

Is there a way to ensure that all images maintain the same height and width using CSS percentages, rather than set pixel values? I'm working on displaying images in circles, where most are uniform in size but a few outliers distort the shape. The wide ...

Making an "associated" route the active route within Aurelia

In my Aurelia application, I have implemented two routes: a list route called Work and a detail route called WorkDetail. Currently, only the list route is visible in the navigation menu: Home | *Work* | Contact | . . . When users navigate to the W ...

Encounter a critical issue while making a JSON request using Kendo UI

I am facing an issue at my workplace where I need to integrate Angular.js with ASP.NET MVC. Currently, I am trying to build a simple application that features a Kendo UI grid on the front page. In my App.js file, I am fetching data from the Data Controller ...

Using a function as an argument within an Angular directive

Looking for a solution to pass a promise-returning function into a directive? Here's what I'm currently doing: In the parent controller, I've created a callback: $scope.myCb = function(data) { console.log(data); } Directive Scope: sco ...

Tips for moving an element to the end of an array

Patients' data is stored in the MongoDB database, and all patients are mapped through on the frontend to display a list. An additional boolean value indicates whether a patient is archived or not. If a patient is archived, it should be displayed at th ...

Sending dynamic information to bootstrap's modal using props in VueJS

I'm currently working on a personal project and encountering an issue with the bootstrap modal. My project involves a list of projects, each one contained within a card element. The problem arises when I attempt to display details for each project by ...

Adding a thousand separator feature to a React Mui TextField

I'm having trouble with my TextField in MUI. I have successfully separated the digits, but now I want to add a thousand separator to the value. Here is my code snippet: <TextField size='small' label ...

Tips for transferring data between iframes on separate pages

I am currently working on implementing a web calendar module within an iframe on page-b. This module consists of 1 page with two sections. Upon entering zipcodes and house numbers, the inputs are hidden and the calendar is displayed. The technology used he ...

Trouble installing NPM packages from Artifactory on Windows 10

Problem Description: I am utilizing Artifactory for my NPM packages. When attempting to install them on "Windows - 7", everything is functioning correctly. However, on "Windows - 10" an error is being displayed and the packages are not installing. Error M ...

Explore the flexibility of npm by installing and utilizing various versions of a specific package

Is it possible to install and utilize different versions of packages in npm? Installation can be done as follows: npm install -g <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1d6d7c7e767c7a78737c70785d2f3325">[email p ...

Is it possible for me to utilize this code for logging in through a dialog box?

Here is the code snippet I have on the client side: <p>Username:</p> <p><asp:TextBox ID="tbUsername" runat="server"></asp:TextBox></p> <p>Password:</p> <p><asp:TextBox ID="tbPassword" runat="server ...

Angular does not seem to support drop and drag events in fullCalendar

I am looking to enhance my fullCalendar by adding a drag and drop feature for the events. This feature will allow users to easily move events within the calendar to different days and times. Below is the HTML code I currently have: <p-fullCalendar deep ...

NextJS was throwing a warning at me, while Firebase hosting was giving me an error regarding the absence of unique keys for children in lists, even though I

I've been troubleshooting this warning for quite some time, but I can't seem to resolve it. The warning reads as follows: Warning: Each child in a list should have a unique "key" prop. Check the top-level render call using <ul>. ...

getting the child td element within a tr using a variable that changes dynamically

I'm facing an issue where I am trying to access the <td> of a <tr> using the jQuery .eq() function. The code snippet below illustrates what I am attempting: var foundElement = 3; var values = $(this).children("td:nth-child('" + foun ...

I'm new to this, but can someone explain why I'm being redirected to the register_db.php page when I click on the register button?

Why when I click the register button, it redirects me to the register_db.php page instead of sending the data to the database and keeping me on the same register.php page? I want the data to be sent to the database without changing the webpage. register.p ...

Tips for implementing events with AngularJS Bootstrap Colorpicker

I am having trouble understanding how events function with Angular Bootstrap Colorpicker. I have forked a Plunker from the developer's example. Unfortunately, there are no examples provided for using events. It would be great if events like colorpick ...

Steps for setting the value of a textbox within a bootstrap popover

When a user clicks on an Anchor element, I am displaying a Bootstrap popover using the following JQuery code. Jquery $("[data-toggle=popover]").popover({ trigger: 'click', placement: "top", html: true, ...

Issue with Ember Select not updating selection binding when populated by another Ember Select

New to Ember.js and grappling with the binding of selection in Select views to the controller. The template I am working with is as follows: {{view Ember.Select contentBinding="content" selectionBinding="selectedCompany" optionLabelPath="content.nam ...

lint-staged executes various commands based on the specific folder

Within my project folder, I have organized the structure with two subfolders: frontend and backend to contain their respective codebases. Here is how the root folder is set up: - backend - package.json - other backend code files - frontend - p ...