使用 CSS3 使 Div 元素遵循弯曲路径

问题描述 投票:0回答:2

所以基本理念是在一张弧形桌子上安排 1 - 9 个座位,就好像您正在通过第一人称视角观看它们一样。我正在尝试获取

div
元素,这些元素将成为在另一个
div
元素外部流动的座位,该元素具有边界半径,使其成为半椭圆形圆圈。我发现了一些示例,其中一个元素被动画化以弧形流过容器,但我需要 div/seats 是静态的。我正在寻找任何可以引导我走上正确道路的想法或例子。

css css-shapes css-transforms
2个回答
16
投票

在椭圆上找到点并平移:

如果您的长方形圆类似于椭圆形,那么您可以使用数学公式在椭圆形上找到点,然后将每个

div
元素转换为该特定点。

计算椭圆上点(x,y)

的数学公式
(a * cos(t), b * sin(t))
。在此公式中,
a
表示椭圆在 x 轴上的半径,
b
表示椭圆在 y 轴上的半径,
t
表示以弧度为单位的角度。角度(弧度)= 角度(度数)* pi / 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>

enter image description here

注意: 坐标是近似值,因此它们可能无法 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

 元素造成任何变形。第二个是粗略的想法,避免了复杂的三角计算。


0
投票
为哈利的答案提供现代更新。相同的事情(或多或少),但没有实际必须事先进行数学计算的麻烦

.container { --radiusX: 300px; --radiusY: 200px; background: red; height: 4px; margin-left: calc( var( --radiusX) + 2rem); margin-top: calc( var( --radiusY) + 2rem); position: relative; width: 4px; &:before { border: 1px solid black; border-radius: 50%; content: ' '; left: calc( var( --radiusX) * -1); display: block; height: calc( var( --radiusY) * 2); position: absolute; top: calc( var( --radiusY) * -1); width: calc( var( --radiusX) * 2); } div { --t: calc( var( --angle) * pi / 180); height: 10px; left: calc( var( --radiusX) * cos( var( --t))); position: absolute; top: calc( var( --radiusY) * sin( var( --t))); width: 10px; &:after { --size: 25px; background: red; border-radius: 50%; bottom: 0; content: ''; right: 0; height: var( --size); position: absolute; width: var( --size); } &:nth-child(n+4):after { background: orange; } &:nth-child(n+7):after { background: green; } &:nth-child(1) { --angle: 180; } &:nth-child(2) { --angle: 202.5; } &:nth-child(3) { --angle: 225; } &:nth-child(4) { --angle: 247.5; } &:nth-child(5) { --angle: 270; } &:nth-child(6) { --angle: 292.5; } &:nth-child(7) { --angle: 315; } &:nth-child(8) { --angle: 337.5; } &:nth-child(9) { --angle: 360; } } }
<div class="container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.