更新时间:2022-10-21 09:53:09
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.
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.
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'];
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';
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
.
div
svar 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>
div
s Positioned Evenlyvar setup = function() {
var radius = 150;
var main = document.getElementById('main');
var mainHeight = parseInt(window.getComputedStyle(main).height.slice(0, -2));
var theta = [0, (2 * (Math.PI / 15)), (4 * (Math.PI / 15)), (2 * (Math.PI / 5)), (8 * (Math.PI / 15)), (2 * (Math.PI / 3)), (4 * (Math.PI / 5)), (14 * (Math.PI / 15)), (16 * (Math.PI / 15)), (6 * (Math.PI / 5)), (4 * (Math.PI / 3)), (22 * (Math.PI / 15)), (8 * (Math.PI / 5)), (26 * (Math.PI / 15)), (28 * (Math.PI / 15))];
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 < 15; 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>
div
svar 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 / 12, Math.PI / 6, Math.PI / 4, Math.PI / 3, 5 * (Math.PI / 12), Math.PI / 2, 7 * (Math.PI / 12), 2 * (Math.PI / 3), 3 * (Math.PI / 4), 5 * (Math.PI / 6), 11 * (Math.PI / 12), Math.PI, 13 * (Math.PI / 12), 7 * (Math.PI / 6), 5 * (Math.PI / 4), 4 * (Math.PI / 3), 17 * (Math.PI / 12), 3 * (Math.PI / 2), 19 * (Math.PI / 12), 5 * (Math.PI / 3), 7 * (Math.PI / 4), 11 * (Math.PI / 6), 23 * (Math.PI / 12)];
var circleArray = [];
var colors = ['red', 'green', 'purple', 'black', 'orange', 'yellow', 'maroon', 'grey', 'lightblue', 'tomato', 'pink', 'maroon', 'cyan', 'magenta', 'blue', 'chocolate', 'darkslateblue', 'coral', 'blueviolet', 'burlywood', 'cornflowerblue', 'crimson', 'darkgoldenrod', 'olive', 'sienna'];
for (var i = 0; i <= 23; 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>
div
s evenlyThe function generate(n, r, id)
takes three arguments: n
- number of div
s, r
- radius and id
- main
in our case.
var theta = [];
var setup = function(n, r, id) {
var main = document.getElementById(id);
var mainHeight = parseInt(window.getComputedStyle(main).height.slice(0, -2));
var circleArray = [];
var colors = ['red', 'green', 'purple', 'black', 'orange', 'yellow', 'maroon', 'grey', 'lightblue', 'tomato', 'pink', 'maroon', 'cyan', 'magenta', 'blue', 'chocolate', 'darkslateblue', 'coral', 'blueviolet', 'burlywood', 'cornflowerblue', 'crimson', 'darkgoldenrod', 'olive', 'sienna', 'red', 'green', 'purple', 'black', 'orange', 'yellow', 'maroon', 'grey', 'lightblue', 'tomato', 'pink', 'maroon', 'cyan', 'magenta', 'blue', 'chocolate', 'darkslateblue', 'coral', 'blueviolet', 'burlywood', 'cornflowerblue', 'crimson', 'darkgoldenrod', 'olive', 'sienna'];
for (var i = 0; i < n; i++) {
var circle = document.createElement('div');
circle.className = 'circle number' + i;
circleArray.push(circle);
circleArray[i].posx = Math.round(r * (Math.cos(theta[i]))) + 'px';
circleArray[i].posy = Math.round(r * (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]);
}
};
var generate = function(n, r, id) {
var frags = 360 / n;
for (var i = 0; i <= n; i++) {
theta.push((frags / 180) * i * Math.PI);
}
setup(n, r, id)
}
generate(40, 150, 'main');
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>
div
s on an EllipseThe equation for a co-ordinate on an ellipse is:
(x, y) = (rx * cos(θ), ry * sin(θ))
where, rx
is the radius along X-axis and ry
is the radius along Y-axis.
In this case, the function generate(n, rx, ry, id)
takes four arguments, where n
is the number of div
s, rx
and ry
are the radii along the X and Y-axis respectively and finally id
is the id
of the div
that you want to append your elliptically arranged div
s in.
var theta = [];
var setup = function(n, rx, ry, id) {
var main = document.getElementById(id);
var mainHeight = parseInt(window.getComputedStyle(main).height.slice(0, -2));
var circleArray = [];
var colors = ['red', 'green', 'purple', 'black', 'orange', 'yellow', 'maroon', 'grey', 'lightblue', 'tomato', 'pink', 'maroon', 'cyan', 'magenta', 'blue', 'chocolate', 'darkslateblue', 'coral', 'blueviolet', 'burlywood', 'cornflowerblue', 'crimson', 'darkgoldenrod', 'olive', 'sienna', 'red', 'green', 'purple', 'black', 'orange', 'yellow', 'maroon', 'grey', 'lightblue', 'tomato', 'pink', 'maroon', 'cyan', 'magenta', 'blue', 'chocolate', 'darkslateblue', 'coral', 'blueviolet', 'burlywood', 'cornflowerblue', 'crimson', 'darkgoldenrod', 'olive', 'sienna'];
for (var i = 0; i < n; i++) {
var circle = document.createElement('div');
circle.className = 'circle number' + i;
circleArray.push(circle);
circleArray[i].posx = Math.round(rx * (Math.cos(theta[i]))) + 'px';
circleArray[i].posy = Math.round(ry * (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]);
}
};
var generate = function(n, rx, ry, id) {
var frags = 360 / n;
for (var i = 0; i <= n; i++) {
theta.push((frags / 180) * i * Math.PI);
}
setup(n, rx, ry, id)
}
generate(16, 150, 75, 'main');
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>
Here's a more flexible version with start offset, clock wise and anti-clock wise functionality.
/*
Usage: Position.ellipse(n, rx, ry, so, wh, idd, cls, cw);
where n = number of divs,
rx = radius along X-axis,
ry = radius along Y-axis,
so = startOffset,
wh = width/height of divs,
idd = id of main div(ellipse),
cls = className of divs;
cw = clockwise(true/false)
*/
var Position = {
ellipse: function(n, rx, ry, so, wh, idd, cls, cw) {
var m = document.createElement('div'),
ss = document.styleSheets;
ss[0].insertRule('#' + idd + ' { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); border-radius: 50%; box-shadow: inset 0 0 ' + wh + 'px ' + wh / 4 + 'px black; background: rgba(0, 0, 0, 0.2); width: ' + String((rx * 2) + wh) + 'px; height: ' + String((ry * 2) + wh) + 'px; }', 1);
ss[0].insertRule('.' + cls + '{ position: absolute; background: black; color: papayawhip; text-align: center; font-family: "Open Sans Condensed", sans-serif; border-radius: 50%; transition: transform 0.2s ease; width: ' + wh + 'px; height: ' + wh + 'px; line-height: ' + wh + 'px;}', 1);
ss[0].insertRule('.' + cls + ':hover { transform: scale(1.2); cursor: pointer; background: rgba(0, 0, 0, 0.8); }', 1);
m.id = idd;
for (var i = 0; i < n; i++) {
var c = document.createElement('div');
c.className = cls;
c.innerHTML = i + 1;
c.style.top = String(ry + -ry * Math.cos((360 / n / 180) * (i + so) * Math.PI)) + 'px';
c.style.left = String(rx + rx * (cw ? Math.sin((360 / n / 180) * (i + so) * Math.PI) : -Math.sin((360 / n / 180) * (i + so) * Math.PI))) + 'px';
m.appendChild(c);
}
document.body.appendChild(m);
}
}
Position.ellipse(20, 150, 150, 0, 42, 'main', 'circle', true);
@import url(http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300);
body {
margin: 0 auto;
background: rgb(198, 193, 173);
}