Home > Software design >  How to avoid overlapping of random numbers?
How to avoid overlapping of random numbers?

Time:02-08

On Clicking button Click Me! How to avoid overlapping of random numbers? It will generate random numbers but there are some numbers which are overlapping how to avoid this... , Here I am not talking about duplicacy of random numbers , I want to avoid overlapping of random numbers....

const circle = document.querySelector(".circle");
const addNumBtn = document.querySelector('#addNumBtn')


function randomValue() {
  let random = Math.floor(Math.random() * 50)   1;
  return random;
}
function randomColor(){
  let r = Math.floor(Math.random() * 255)   1;
  let g = Math.floor(Math.random() * 255)   1;
  let b = Math.floor(Math.random() * 255)   1;
  return `rgba(${r},${g},${b})`
}
function randomSize(){
  let size = Math.floor(Math.random() * 30)   8;
  return `${size}px`
}
function randNum() {
  let randnum = document.createElement("p");
  randnum.classList.add('numStyle')
  randnum.style.color=randomColor();
  randnum.style.fontSize=randomSize();
  randnum.textContent = randomValue();
  randnum.style.position = 'absolute'
  randnum.style.top = `${randomValue()}px`
  randnum.style.left = `${randomValue()}px`
  randnum.style.bottom = `${randomValue()}px`
  randnum.style.right = `${randomValue()}px`
  circle.append(randnum);
}


addNumBtn.addEventListener('click',randNum)
.circle {
  aspect-ratio: 1;
  width: 300px;
  background-color: black;
  border-radius: 50%;
  position: relative;
  overflow:hidden;
}

#addNumBtn{
  position:absolute;
  top:0;
  left:0;
}

.numStyle{
  font-family:"roboto",sans-serif;
}
//On Clicking button Click Me! I want to place all the random numbers inside the circle 
//together not one by one, at a time all numbers should be placed inside the circle by 
//clicking 
the button Click Me!
<div id="container"></div>
    <div ></div>
</div>
    <button id="addNumBtn">Click Me!</button>

CodePudding user response:

You need to loop over the random number generator for the amount of times you wish to display the created number element in the circle. You can create and return an array of values in randomValue() function, then loop over that array in randNum() function.

Also, I assume you want the output of the appended element to spread out over the entirety of the circle element yes? If so, you need to randomize the position of the element relative to the size of the circle, not the randomValue functions returned value.

EDIT:

OP asked after posting answer: There are some numbers at circles border side which are not properly visible how to solve that?

Because of the box model of elements, the border of the circle element is square, not round though the viewable content of the circle element is round due to its border-radius css.

You can use a helper function that will determine if the randomly generated numbers for x and y, or left and top, are within the border-radius of the circle element using the size of the radius and the center point of the x and y coords of the circle.

Credit for helper function: Simon Sarris:

function pointInCircle(x, y, cx, cy, rad) {
  const distancesquared = (x - cx) * (x - cx)   (y - cy) * (y - cy);
  return distancesquared <= rad * rad;
}

We wrap everything inside a while loop that checks if a counter has reached 50. Inside the loop we run the function that creates the randomly generated positions -> randomPos(). Then we run a conditional that will check to see if the randomly generated points are within the circle using the function pointInCircle(x, y, cx, cy, rad). If this conditional returns true we create the number elements, style and append the number elements to the circle and iterate our counter value by one.

const circle = document.querySelector(".circle");
const addNumBtn = document.querySelector('#addNumBtn');
// we set the width of the circle element in JS and pass
// it to CSS using a css variable and the root element
const circleWidth = 350;
document.documentElement.style.setProperty('--circleWidth', `${circleWidth}px`);

// NOTE: '~~' -> is quicker form of writing Math.floor() 
// runs faster on most browsers.

function randomPos(min, max) {
  return ~~(Math.random() * (max - min   1)   min)
}

// return a random value between 1 and 50
function randomValue(){
  return ~~(Math.random() * 50)   1;
}

function randomColor() {
  let r = ~~(Math.random() * 255)   1;
  let g = ~~(Math.random() * 255)   1;
  let b = ~~(Math.random() * 255)   1;
  return `rgba(${r},${g},${b})`
}

function randomSize() {
  let size = ~~(Math.random() * 30)   8;
  return `${size}px`
}

// add a helper function to find the center of the 
// circle and calculate distance to the edge of circle
// x and y are the randomly generated points
// cx, cy are center of circle x and y repsectively
// rad is circle radius
function pointInCircle(x, y, cx, cy, rad) {
  const distancesquared = (x - cx) * (x - cx)   (y - cy) * (y - cy);
  return distancesquared <= rad * rad;
}

// you can remove valArray array if you do not want the 50 numbers to not be repeated
const valArray = [];

function randNum() {
  // add a counter
  let count = 1;
  // while loop to check if the counter has reached the target 50
  while (count <= 50) {
    // set the randomly generated val
    let val = randomValue();
    // random size = string with px added
    let randSize = randomSize();
    // random size = the exact number => typeof number 
    let posSize = randSize.split('px')[0];
    // an array to hold our randomly positioned number values
    // uses helper function randonPos
    // pass in the 1 and the circle width minus the font size
    let ran = [randomPos(1, circleWidth - posSize), randomPos(1, circleWidth - posSize)];
    // conditional to check bounds of circle using helper function
    // we pass in the ran array, center points and radius
    // we add buffers to accommodate for the font size
    // you can remove !valArray.includes(val) if you do not want the 50 numbers to not be repeated
    if (pointInCircle(ran[0], ran[1], circleWidth/2-posSize, circleWidth/2-posSize, circleWidth / 2 - posSize) && !valArray.includes(val)) {
      // you can remove valArray.push(val); if you do not want the 50 numbers to not be repeated
      valArray.push(val);
      // if the conditional returns true, 
      // create the element, style and append
      let randnum = document.createElement("p");
      randnum.classList.add('numStyle');
      randnum.style.color = randomColor();
      randnum.style.fontSize = randSize;
      randnum.textContent = val;
      randnum.style.position = 'absolute';
      randnum.style.top = `${ran[0]}px`;
      randnum.style.left = `${ran[1]}px`;
      circle.append(randnum);
      // iterate the counter
      count  ;
    }
  }
}

addNumBtn.addEventListener('click', randNum)
html {
  --circle-width: 300px;
}

.circle {  
  aspect-ratio: 1;
  width: var(--circleWidth);
  background-color: black;
  border-radius: 50%;
  position: relative;
  overflow: hidden;
  padding: .5rem;
}


#addNumBtn {
  position: absolute;
  top: 0;
  left: 0;
}

.numStyle {
  font-family: "roboto", sans-serif;
}
//On Clicking button Click Me! I want to place all the random numbers inside the circle //together not one by one, at a time all numbers should be placed inside the circle by //clicking the button Click Me!
<div id="container"></div>
<div >
</div>
<button id="addNumBtn">Click Me!</button>

  •  Tags:  
  • Related