Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
254 views
in Technique[技术] by (71.8m points)

html - Positioning divs in a circle using JavaScript

I am trying to position 15 div elements evenly in a circle with a radius of 150px. I'm using the following code, which seems to give an oddly eccentric ellipse that overlaps.

Fiddle

// Hold a global reference to the div#main element.  Initially assign it ... somewhere useful :)
var main = document.getElementById('main');
var circleArray = [];

// Move a circle based on the distance of the approaching mouse
var moveCircle = function(circle, dx, dy) {

};

// Look at all the circle elements, and figure out if any of them have to move.
var checkMove = function() {

};
var setup = function() {
  for (var i = 0; i < 15; i++) {
    //create element, add it to the array, and assign it's coordinates trigonometrically.
    //Then add it to the "main" div
    var circle = document.createElement('div');
    circle.className = 'circle number' + i;
    circleArray.push(circle);
    circleArray[i].posx = Math.round((150 * Math.cos(i * (2 * Math.PI / 15)))) + 'px';
    circleArray[i].posy = Math.round((150 * Math.sin(i * (2 * Math.PI / 15)))) + 'px';
    circleArray[i].style.position = "relative";
    circleArray[i].style.top = circleArray[i].posy;
    circleArray[i].style.left = circleArray[i].posx;
    main.appendChild(circleArray[i]);
  }
};
setup();
window.addEventListener('load', function() {

});
div {
  box-sizing: border-box;
}
div#main {
  position: absolute;
  left: 50%;
  top: 50%;
}
div.circle {
  position: absolute;
  width: 20px;
  height: 20px;
  border: 2px solid black;
  border-radius: 10px;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
}
<div id="main"></div>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First of all, the equation for a co-ordinate on a circle is simply:

(x, y) = (r * cos(θ), r * sin(θ))

where, r is the radius of a circle and θ is the angle in radians.


The reason why your code is creating an eccentric ellipse is because when you assign the .top and .left CSS values, you are not considering that it will actually take the top-left corner as its reference. I've fixed your code and now it creates a perfect circle.

Changes made to your code:

  1. Added an array theta that holds all the angles.

    var theta = [0, Math.PI / 6, Math.PI / 4, Math.PI / 3, Math.PI / 2, 2 * (Math.PI / 3), 3 * (Math.PI / 4), 5 * (Math.PI / 6), Math.PI, 7 * (Math.PI / 6), 5 * (Math.PI / 4), 4 * (Math.PI / 3), 3 * (Math.PI / 2), 5 * (Math.PI / 3), 7 * (Math.PI / 4), 11 * (Math.PI / 6)];
    

    The image below shows all the angles I've used.

    enter image description here

  2. Added an array colors that holds different colors.

    var colors = ['red', 'green', 'purple', 'black', 'orange', 'yellow', 'maroon', 'grey', 'lightblue', 'tomato', 'pink', 'maroon', 'cyan', 'magenta', 'blue', 'chocolate', 'DarkSlateBlue'];
    
  3. Made changes to your trigonometric equations.

    circleArray[i].posx = Math.round(radius * (Math.cos(theta[i]))) + 'px';
    circleArray[i].posy = Math.round(radius * (Math.sin(theta[i]))) + 'px';
    
  4. Changed the way .top and .left are assigned.

    circleArray[i].style.top = ((mainHeight / 2) - parseInt(circleArray[i].posy.slice(0, -2))) + 'px';
    circleArray[i].style.left = ((mainHeight / 2) + parseInt(circleArray[i].posx.slice(0, -2))) + 'px';
    

    where mainHeight is the height of the #main div.


[1] 16 divs

Demo on Fiddle

var setup = function() {
  var radius = 150;
  var main = document.getElementById('main');
  var mainHeight = parseInt(window.getComputedStyle(main).height.slice(0, -2));
  var theta = [0, Math.PI / 6, Math.PI / 4, Math.PI / 3, Math.PI / 2, 2 * (Math.PI / 3), 3 * (Math.PI / 4), 5 * (Math.PI / 6), Math.PI, 7 * (Math.PI / 6), 5 * (Math.PI / 4), 4 * (Math.PI / 3), 3 * (Math.PI / 2), 5 * (Math.PI / 3), 7 * (Math.PI / 4), 11 * (Math.PI / 6)];
  var circleArray = [];
  var colors = ['red', 'green', 'purple', 'black', 'orange', 'yellow', 'maroon', 'grey', 'lightblue', 'tomato', 'pink', 'maroon', 'cyan', 'magenta', 'blue', 'chocolate', 'DarkSlateBlue'];
  for (var i = 0; i < 16; i++) {
    var circle = document.createElement('div');
    circle.className = 'circle number' + i;
    circleArray.push(circle);
    circleArray[i].posx = Math.round(radius * (Math.cos(theta[i]))) + 'px';
    circleArray[i].posy = Math.round(radius * (Math.sin(theta[i]))) + 'px';
    circleArray[i].style.position = "absolute";
    circleArray[i].style.backgroundColor = colors[i];
    circleArray[i].style.top = ((mainHeight / 2) - parseInt(circleArray[i].posy.slice(0, -2))) + 'px';
    circleArray[i].style.left = ((mainHeight / 2) + parseInt(circleArray[i].posx.slice(0, -2))) + 'px';
    main.appendChild(circleArray[i]);
  }
};
setup();
div#main {
  height: 300px;
  width: 300px;
  position: absolute;
  margin: 0 auto;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
}
div.circle {
  position: absolute;
  width: 20px;
  height: 20px;
  border: 2px solid black;
  border-radius: 50%;
}
body {
  margin: 0 auto;
  background: papayawhip;
}
<div id="main"></div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...