So the basic idea is 1 - 9 seats at a curved table as though you are looking at them through first person view. I'm trying to get div
elements which would be seats to flow on the outside of another div
element that has a border radius to make it a semi oblong circle. I've found a few examples with an element being animated to flow across the container in an arc, but I will need the div/seats to be static. I am looking for any ideas or examples that can lead me in the right path.
Finding points on ellipse and translating:
If your oblong circle resembles an ellipse then you can find points on the ellipse using mathematical formula and then translate each div
element to that particular point.
Mathematical formula for calculating point (x,y)
on an ellipse is(a * cos(t), b * sin(t))
. In this formula, a
represents the radius of the ellipse in x-axis, b
represents the radius of the ellipse in the y-axis and t
represents the angle in radians. Angle in radians = Angle in degrees * pi / 180.
To make use of this approach, we do the following:
div
elements absolutely at the centre point of the ellipse.(x,y)
corresponding to each angle and translate the div
to its place by using transform: translateX(...) translateY(...)
. The angles are in steps of 22.5 deg because there are a total 9 elements to be placed within 180 degrees..container {
position: relative;
height: 400px;
width: 600px;
padding: 12.5px;
border: 1px solid;
border-radius: 50%;
}
div > div {
position: absolute;
top: 0px;
left: 0px;
height: 50%;
width: 50%;
transform-origin: bottom right;
}
div > div:after {
position: absolute;
content: '';
bottom: 0px;
right: 0px;
height: 25px;
width: 25px;
background: black;
border-radius: 50%;
transform: translateX(50%) translateY(50%);
}
div > div:after {
background: red;
}
div > div:nth-child(n+4):after {
background: orange;
}
div > div:nth-child(n+7):after {
background: green;
}
div > div:nth-child(1) {
transform: translateX(-300px) translateY(0px);
}
div > div:nth-child(2) {
transform: translateX(-277.17px) translateY(-76.5px);
}
div > div:nth-child(3) {
transform: translateX(-212.13px) translateY(-141.42px);
}
div > div:nth-child(4) {
transform: translateX(-114.80px) translateY(-184.77px);
}
div > div:nth-child(5) {
transform: translateX(0px) translateY(-200px);
}
div > div:nth-child(6) {
transform: translateX(114.80px) translateY(-184.77px);
}
div > div:nth-child(7) {
transform: translateX(212.13px) translateY(-141.42px);
}
div > div:nth-child(8) {
transform: translateX(277.17px) translateY(-76.5px);
}
div > div:nth-child(9) {
transform: translateX(300px) translateY(0px);
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Note: The coordinates are approximate values and hence they may not align 100% correctly.
Using rotation and scale transform: (original idea)
The below snippet provides a very rough idea on how to position the elements along a circle. It is by no means a complete output but you can adapt it to fit your needs.
The components are very simple:
div
elements for each seat. All of them have 50% width
of the container and 50% height
.:after
) attached to the child div
elements that produce the circle/dot like seats and they are absolutely positioned at the bottom of the container.div
element is rotated by 180/(n-1)
deg as we need them to be positioned around a semicircle..container {
position: relative;
height: 200px;
width: 200px;
border: 1px solid;
border-radius: 50%;
}
div > div {
position: absolute;
top: 0px;
left: 0px;
height: 50%;
width: 50%;
transform-origin: bottom right;
}
div > div:after {
position: absolute;
content: '';
bottom: 0px;
left: 0px;
height: 25px;
width: 25px;
background: black;
border-radius: 50%;
transform: translateY(50%);
}
div > div:nth-child(1) {
transform: rotate(0deg);
}
div > div:nth-child(2) {
transform: rotate(22.5deg);
}
div > div:nth-child(3) {
transform: rotate(45deg);
}
div > div:nth-child(4) {
transform: rotate(67.5deg);
}
div > div:nth-child(5) {
transform: rotate(90deg);
}
div > div:nth-child(6) {
transform: rotate(112.5deg);
}
div > div:nth-child(7) {
transform: rotate(135deg);
}
div > div:nth-child(8) {
transform: rotate(157.5deg);
}
div > div:nth-child(9) {
transform: rotate(180deg);
}
div > div:after {
background: red;
}
div > div:nth-child(n+4):after {
background: orange;
}
div > div:nth-child(n+7):after {
background: green;
}
/* Just for demo */
.container{
transition: all 1s;
}
.container:hover {
height: 400px;
width: 400px;
transition: all 1s;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
There is a simple method to convert the above into an oblong circle and that would be to scale the container in the X-axis. One point to note is that the children would also get scaled and hence would need to be reverse transformed.
.container {
position: relative;
height: 200px;
width: 200px;
border: 1px solid;
border-radius: 50%;
transform: scaleX(1.25);
transform-origin: left;
}
div > div {
position: absolute;
top: 0px;
left: 0px;
height: 50%;
width: 50%;
transform-origin: bottom right;
}
div > div:after {
position: absolute;
content: '';
bottom: 0px;
left: 0px;
height: 25px;
width: 25px;
background: black;
border-radius: 50%;
transform: translateY(50%);
}
div > div:nth-child(1) {
transform: rotate(0deg);
}
div > div:nth-child(2) {
transform: rotate(22.5deg);
}
div > div:nth-child(3) {
transform: rotate(45deg);
}
div > div:nth-child(4) {
transform: rotate(67.5deg);
}
div > div:nth-child(5) {
transform: rotate(90deg);
}
div > div:nth-child(6) {
transform: rotate(112.5deg);
}
div > div:nth-child(7) {
transform: rotate(135deg);
}
div > div:nth-child(8) {
transform: rotate(157.5deg);
}
div > div:nth-child(9) {
transform: rotate(180deg);
}
div > div:after {
background: red;
}
div > div:nth-child(n+4):after {
background: orange;
}
div > div:nth-child(n+7):after {
background: green;
}
/* Just for demo */
.container {
transition: all 1s;
}
.container:hover {
height: 400px;
width: 400px;
transform: scaleX(1.25);
transform-origin: left;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
The first method is the perfect and recommended approach as it doesn't cause any distortion to the div
elements. The second is rough idea which avoids complex trigonometric calculations.