What is the best way to ensure that circles only touch each other by their edges?

Trying to align three circles touching each other has been a challenge for me. Although I have successfully managed to make two touch, the third one remains elusive. How can I ensure that all three circles are in contact with each other, especially when the radius of each circle is subject to change?

I had considered using absolute positioning, but I'm uncertain about how it would interact with dynamic radii.

If anyone has suggestions or guidance on achieving this, I would greatly appreciate it. https://i.sstatic.net/1ywxT.jpg

View CodeSandbox

<!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>Static Template</title>
    <style>
      .circle-diagram {
        height: 100%;
        min-height: 190px;
      }
      .circle-diagram .solar-grid-wrapper {
        display: flex;
      }
      .circle-diagram .yellow-circle,
      .circle-diagram .yellow-circle-shadow {
        border-radius: 50%;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        color: #fff;
        font-size: 12px;
        width: 130px;
        height: 130px;
        background-color: #feda02;
      }
      .circle-diagram .green-circle,
      .circle-diagram .green-circle-shadow {
        border-radius: 50%;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        color: #fff;
        font-size: 12px;
        width: 91.05px;
        height: 91.05px;
        background-color: #25dc8a;
        left: 124px;
        top: 15px;
      }
      .circle-diagram .blue-circle,
      .circle-diagram .blue-circle-shadow {
        border-radius: 50%;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        color: #fff;
        font-size: 12px;
        width: 119.8px;
        height: 119.8px;
        background: #3d7ff9;
        left: 108px;
        top: 106px;
      }
      .circle-diagram .symbol {
        height: 15px;
        margin-bottom: 8px;
      }
      .circle-diagram .value {
        z-index: 10;
        opacity: 1;
        font-weight: 550;
      }

      #randomButton {
        margin-top: 60px;
        border: 1px solid black;
        background: #3d7ff9;
        padding: 10px;
      }
    </style>
  </head>
  <body>
    <div class="circle-diagram">
      <div class="solar-grid-wrapper">
        <div
          class="yellow-circle"
          id="circle1"
          style="width: 150px; height: 150px;"
        >
          <div class="value">Cool text 1</div>
        </div>
        <div
          class="blue-circle"
          id="circle2"
          style="width: 160px; height: 160px;"
        >
          <div class="value">Cool text 2</div>
        </div>
      </div>
      <div
        class="green-circle"
        id="circle3"
        style="width: 222px; height: 222px;"
      >
        <div class="value">Cool text 3</div>
      </div>
    </div>

    <button id="randomButton">Random Width</button>
  </body>
  <script>
    document.getElementById("randomButton").addEventListener(
      "click",
      function() {
        function random(min, max) {
          return Math.round(Math.random() * Math.abs(max - min) + min);
        }
        const randomNumber1 = random(150, 220);
        const randomNumber2 = random(150, 220);
        const randomNumber3 = random(150, 220);
        document.getElementById("circle1").style.width = `${randomNumber1}px`;
        document.getElementById("circle1").style.height = `${randomNumber1}px`;
        document.getElementById("circle2").style.width = `${randomNumber2}px`;
        document.getElementById("circle2").style.height = `${randomNumber2}px`;
        document.getElementById("circle3").style.width = `${randomNumber3}px`;
        document.getElementById("circle3").style.height = `${randomNumber3}px`;
      },
      false
    );
  </script>
</html>

Answer №1

document.getElementById("randomButton").addEventListener(
  "click",
  function() {
    function random(min, max) {
      return Math.round(Math.random() * Math.abs(max - min) + min);
    }
    const r1 = random(150, 220);
    const r2 = random(150, 220);
    const r3 = random(150, 220);
    var circle1 = document.getElementById("circle1"),
      circle2 = document.getElementById("circle2"),
      circle3 = document.getElementById("circle3");
   
    var h =(r1>r2)? Math.sqrt((r1/2+r3/2)*(r1/2+r3/2)-r1*r1/4):Math.sqrt((r2/2+r3/2)*(r2/2+r3/2)-r2*r2/4),
    h2 = (r1>r2)? (r1+r3)/2:(r2+r3)/2,
    alpha = (r1>r2)?r1/r2:r2/r1;
    
    circle3.style.left =`${alpha*(h-h2)}px`;
    circle3.style.top =`${(5/4)*alpha*(r1-r2)/2}px`;
    
    circle1.style.width = `${r1}px`;
    circle1.style.height = `${r1}px`;
    circle2.style.width = `${r2}px`;
    circle2.style.height = `${r2}px`;
    circle3.style.width = `${r3}px`;
    circle3.style.height = `${r3}px`;
  },
  false
);
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.circle-diagram {
  display: flex;
  align-items: center;
 
}

.circle-diagram .solar-grid-wrapper {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background: gray;
}

.circle-diagram .yellow-circle,
.circle-diagram .yellow-circle-shadow {
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #fff;
  font-size: 12px;
  width: 130px;
  height: 130px;
  background-color: #feda02;
  position: relative;
}

.circle-diagram .green-circle,
.circle-diagram .green-circle-shadow {
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #fff;
  font-size: 12px;
  background-color: #25dc8a;
  position: relative;
  top: 0;
}

.circle-diagram .blue-circle,
.circle-diagram .blue-circle-shadow {
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #fff;
  font-size: 12px;
  width: 119.8px;
  height: 119.8px;
  background: #3d7ff9;
  position: relative;
}

.circle-diagram .symbol {
  height: 15px;
  margin-bottom: 8px;
}

.circle-diagram .value {
  z-index: 10;
  opacity: 1;
  font-weight: 550;
}

#randomButton {
  margin-top: 60px;
  border: 1px solid black;
  background: #3d7ff9;
  padding: 10px;
}
<!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>Static Template</title>
</head>

<body>
  <div class="circle-diagram">
    <div class="solar-grid-wrapper">
      <div class="yellow-circle" id="circle1" style="width: 160px; height: 160px;">
        <div class="value">Cool text 1</div>
      </div>
      <div class="blue-circle" id="circle2" style="width: 150px; height: 150px;">
        <div class="value">Cool text 2</div>
      </div>
    </div>
    <div class="green-circle" id="circle3" style="width: 222px; height: 222px;top:7.5Px;left:-18px;">
      <div class="value">Cool text 3</div>
    </div>
  </div>

  <button id="randomButton">Random Width</button>
</body>

</html>

Answer №2

Uncertain if this is what you're looking for, but here's a customized example featuring circles touching each other:

<!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>Modified Sample</title>
    <style>
      .circle-diagram {
        height: 100%;
        min-height: 190px;
      }
      .circle-diagram .solar-grid-wrapper {
        display: flex;
      }
      .circle-diagram .yellow-circle,
      .circle-diagram .yellow-circle-shadow {
        border-radius: 50%;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        color: #fff;
        font-size: 12px;
        width: 130px;
        height: 130px;
        background-color: #feda02;
      }
      .circle-diagram .green-circle,
      .circle-diagram .green-circle-shadow {
        border-radius: 50%;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        color: #fff;
        font-size: 12px;
        width: 91.05px;
        height: 91.05px;
        background-color: #25dc8a;
        left: 124px;
        top: 15px;
      }
      .circle-diagram .blue-circle,
      .circle-diagram .blue-circle-shadow {
        border-radius: 50%;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        color: #fff;
        font-size: 12px;
        width: 119.8px;
        height: 119.8px;
        background: #3d7ff9;
        left: 108px;
        top: 106px;
      }
      .circle-diagram .symbol {
        height: 15px;
        margin-bottom: 8px;
      }
      .circle-diagram .value {
        z-index: 10;
        opacity: 1;
        font-weight: 550;
      }

      #randomButton {
        margin-top: 60px;
        border: 1px solid black;
        background: #3d7ff9;
        padding: 10px;
      }
    </style>
  </head>
  <body>
    <div class="circle-diagram">
      <div class="solar-grid-wrapper">
        <div
          class="yellow-circle"
          id="circle1"
          style="width: 150px; height: 150px"
        >
          <div class="value">Awesome text 1</div>
        </div>
        <div
          class="blue-circle"
          id="circle2"
          style="width: 160px; height: 160px;margin-left: -10px"
        >
          <div class="value">Awesome text 2</div>
        </div>
      </div>
      <div
        class="green-circle"
        id="circle3"
        style="width: 222px; height: 222px;margin-top: -30px"
      >
        <div class="value">Awesome text 3</div>
      </div>       
    </div>

    <button id="randomButton">Random Width</button>
  </body>
  <script>
    document.getElementById("randomButton").addEventListener(
      "click",
      function() {
        function random(min, max) {
          return Math.round(Math.random() * Math.abs(max - min) + min);
        }
        const randomNumber1 = random(150, 220);
        const randomMargin2 = random(10, randomNumber1 / 4);
        const randomNumber2 = random(150, 220);
        const randomNumber3 = random(150, 220);
        const randomMargin3 = random(10, randomNumber2 / 4);
        document.getElementById("circle1").style.width = `${randomNumber1}px`;
        document.getElementById("circle1").style.height = `${randomNumber1}px`;
        document.getElementById("circle2").style.width = `${randomNumber2}px`;
        document.getElementById("circle2").style.height = `${randomNumber2}px`;
        document.getElementById("circle2").style.marginLeft = `-${randomMargin2 }px`;
        document.getElementById("circle3").style.width = `${randomNumber3}px`;
        document.getElementById("circle3").style.height = `${randomNumber3}px`;
        document.getElementById("circle3").style.marginTop = `-${randomMargin3 }px`;
      },
      false
    );
  </script>
</html>

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

Issue with Vuex not functioning properly in Nuxt.js

I'm facing an issue with setting the state in Vuex on my Nuxt.js App. It seems to not be working correctly. So, here is how I am trying to set the state using the fetch method: fetch({app, store, route}) { app.$axios.$get(`apps/${route.params ...

What are the advantages of using Yarn instead of NPM? Understanding the distinctions between the two package managers

What sets Yarn apart from NPM? I've been scouring the internet for articles that compare Yarn and NPM, but all I find are resources detailing the equivalent commands between the two. While both seem to offer similar functionalities, such as local cac ...

Generate a list of files and transfer them to an input file

I am currently working on creating a drag and drop area where I can retrieve dataTransfer items using webkitGetAsEntry, and then differentiate between directories and files. My goal is to convert these files into a FileList and transfer them to a file inp ...

Tips for ensuring an element is visible in CUCUMBER JS?

Whenever I run my code, it keeps returning the error message: NoSuchElementError: no such element: Unable to locate element Even though I have set up a wait function, it does not seem to actually wait. The step fails immediately without waiting for the s ...

I'm having trouble sending a string to a WCF service using jQuery AJAX. What's preventing me from sending strings of numbers?

Something strange is happening with my web service when using jquery ajax - I can only pass strings containing numbers. This was never an issue before as I would always just pass IDs to my wcf service. But now that I'm trying something more complex, I ...

"Streamlining data entry with an uncomplicated HTML form input that accepts multiple values from a

As I understand it, a barcode scanner functions as nothing more than a keyboard that transmits keycode 13 after each scan. My task is straightforward: I have a basic form with only one input field and I want the ability to scan numerous barcodes and then c ...

The most effective way to transmit data from an asynchronous call in Node.js while ensuring a reliable fallback routing structure

I have a request function that makes a call to an endpoint and retrieves data from it. When passing this data to an hbs template for rendering, the array is empty due to asynchronicity. Can someone guide me on the correct approach? Below is the code snippe ...

Animating rows in the grid auto property

I am working with a basic css grid that contains X number of grid items. These grid items can vary in size and I need to implement an expander feature. The goal is to initially display only a certain number of rows, but upon clicking a button, the grid wil ...

I recently implemented a delete function in my code that successfully removes a row, but now I am looking to also delete the corresponding data from localStorage in JavaScript

I have successfully implemented a delete function in JavaScript that deletes rows, but I also want to remove the data from local storage. This way, when a user reloads the page, the deleted row will not appear. The goal is to delete the data from local s ...

The location.reload function keeps reloading repeatedly. It should only reload once when clicked

Is there a way to reload a specific div container without using ajax when the client requests it? I attempted to refresh the page with the following code: $('li.status-item a').click(function() { window.location.href=window.location.href; ...

"Unlocking the Potential of Babylon.js and Three.js for Exporting Pur

Currently, I am trying to convert a babylon.js model in .babylon format to either .obj or .stl (or any other format compatible with Maya). After searching for a solution within babylon.js itself, I found that three.js has a "save as obj" function in its ed ...

Using HTML to execute a JavaScript function that transforms images

The script cutImageUp has been previously discussed on SE in a thread about Shattering image using canvas. However, I have encountered a different issue while attempting to use it. The HTML code I implemented seems to be ineffective, and despite my efforts ...

Adding information into material-ui dropdown using React JS

I could use some assistance with populating data into a Dropdown using material-ui in React. I am new to React and unsure about how to achieve this. I know that I can pass props to the dropdown, but it's not very clear to me. Here is my current code: ...

Manipulating webpage content with JavaScript

How can I provide visual feedback to a user while an ajax request is in progress? For example, when a user clicks a 'process' button that triggers an AJAX request to a server-side script, they should see a 'loading...' message and a gra ...

How can I implement a jQuery popup that prompts users to log in or register if they are not currently authenticated?

My JavaScript code includes jQuery and AJAX functionality for a specific action. Whenever a user id is not provided, and there isn't one stored in the session, I aim to prompt the user with a dialog box asking them to either register or log in. Could ...

The manner in which sessionStorage or localStorage is shared between different domains

I am looking to persist data across different domains using sessionStorage or localStorage. How can I achieve this? The data needs to be shared between a Vue project and a React project. English is not my strong suit, so I hope you are able to understand ...

Is there a way to deactivate the Edge mini menu while selecting text in a React application?

I have recently been working on a React web application and managed to create a specialized text selection menu. However, I am facing a challenge in programmatically disabling the default text selection mini menu in React. The image attached illustrates bo ...

Receiving an abundance of alert notifications triggered by the search functionality of jsTree

I've created a function to search for text within the jsTree framework. The goal is to highlight the node if the search text is found. If not, inform the user with a message saying "No node matching the search string, please try again." However, I&a ...

Angular allows users to interact with objects in THREE.js by simply clicking on

I've tried numerous solutions, but none of them seem to work - the cube is in the wrong position and only one face is detected. Since the angular event is easy to call. 1. Insert a tag into the HTML code. <div (click)="onClickCanvas($event)"> ...

Modify the URL parameter when a button is clicked

I want to apologize in advance for not providing more information. If the limited info is not enough, I will remove the question. There's a script that creates a search engine based on another dynamically generated script which is complex and beyond ...