Элементы Div для следования изогнутому пути с помощью CSS3

Таким образом, основная идея заключается в том, что от 1 до 9 мест за изогнутым столом, как будто вы смотрите на них от первого лица. Я пытаюсь получить элементы div, которые будут местами для потока снаружи другого элемента div, который имеет радиус границы, чтобы сделать его полупродолговатым кругом. Я нашел несколько примеров с анимированным элементом, который перемещается по контейнеру по дуге, но мне нужно, чтобы элементы div/seat были статичными. Я ищу любые идеи или примеры, которые могут привести меня на правильный путь.


person jhorton    schedule 03.09.2015    source источник
comment
Вот очень приблизительное представление о том, как его реализовать — jsfiddle.net/5c59m5q4. Недостаточно близко, чтобы публиковать в качестве ответа, и у меня сейчас нет времени на его настройку.   -  person Harry    schedule 03.09.2015
comment
Это отлично сработает, чтобы я начал. И я на самом деле только что подумал о чем-то подобном, когда пошел на прогулку. Спасибо, Гарри, если ты хочешь записать это как ответ, я буду рад сделать это ответом.   -  person jhorton    schedule 03.09.2015
comment
см. это, поскольку оно напоминает знакомую концепцию той, которую вы пытаетесь достигать.   -  person jbutler483    schedule 08.09.2015


Ответы (1)


Нахождение точек на эллипсе и перевод:

Если ваш продолговатый круг напоминает эллипс, вы можете найти точки на эллипсе, используя математическую формулу, а затем перевести каждый элемент div в эту конкретную точку.

Математическая формула для вычисления точки (x,y) на эллипсе is(a * cos(t), b * sin(t)). В этой формуле a представляет собой радиус эллипса по оси X, b представляет собой радиус эллипса по оси Y, а t представляет угол в радианах. Угол в радианах = Угол в градусах * пи / 180.

Чтобы использовать этот подход, мы делаем следующее:

  • Поместите элементы div абсолютно в центральную точку эллипса.
  • Вычислите (x,y), соответствующие каждому углу, и переместите div на его место, используя transform: translateX(...) translateY(...). Углы указаны с шагом 22,5 градуса, потому что всего 9 элементов должны быть размещены в пределах 180 градусов.

.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>

введите описание изображения здесь

Примечание. Координаты являются приблизительными значениями, поэтому они могут не совпадать на 100% правильно.


Использование вращения и преобразования масштаба: (исходная идея)

Фрагмент ниже дает очень приблизительное представление о том, как расположить элементы по кругу. Это ни в коем случае не полный вывод, но вы можете адаптировать его под свои нужды.

Компоненты очень простые:

  • Один контейнерный элемент, который представляет собой круг и служит опорным элементом, относительно которого располагаются сиденья.
  • 9 отдельных div элементов для каждого сиденья. Все они имеют 50% width контейнера и 50% height.
  • Псевдоэлемент (:after), прикрепленный к дочерним элементам div, которые создают круг/точку, как сиденья, и они абсолютно расположены в нижней части контейнера.
  • Каждый дочерний элемент div поворачивается на 180/(n-1) градусов, так как нам нужно, чтобы они располагались вокруг полукруга.

.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>

Существует простой способ преобразовать вышеуказанное в продолговатый круг, и это будет масштабирование контейнера по оси X. Следует отметить, что дочерние элементы также будут масштабироваться и, следовательно, должны быть преобразованы в обратном порядке.

.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>

Первый метод является идеальным и рекомендуемым подходом, поскольку он не вызывает искажения div элементов. Вторая — это грубая идея, позволяющая избежать сложных тригонометрических вычислений.

person Harry    schedule 03.09.2015
comment
Святая математика в плаще чудо!!! Ты выложился на этом. Спасибо за подробный ответ. Я всегда задавался вопросом, почему так много математики было частью учебной программы по информатике, и теперь я знаю. Я постараюсь использовать первый ответ. В очередной раз благодарим за помощь. - person jhorton; 08.09.2015
comment
Собственно, посмотрев на него еще немного, я вижу одну проблему. Мне нужно, чтобы веб-страница была адаптивной. Поэтому, если я использую уравнение, мне нужно будет определить абсолютные высоты и ширины. И установка значений через javascript при изменении размера страницы будет дорогостоящей. Вы знаете, будет ли первый ответ работать с процентами? - person jhorton; 08.09.2015
comment
@jhorton: для первого ответа потребуется, чтобы JS реагировал, потому что позиции рассчитываются на основе радиусов X и Y эллипса. Второй можно сделать отзывчивым без каких-либо дополнительных вычислений, но, как указано в ответе, ему требуется преобразование масштаба, чтобы он стал продолговатым, и это означало бы, что div внутри также будет выглядеть масштабированным. - person Harry; 08.09.2015