使用CSS3让Div元素沿着曲线路径移动

3
所以基本的想法是在一个弯曲的桌子上放置1-9个座位,就像你通过第一人称视角看它们一样。我正在尝试获取 div 元素,这些元素将成为座位,流动到另一个带有边界半径的 div 元素的外部,使其成为半椭圆形。我已经找到了一些例子,其中一个元素被动画流过容器形成一个弧形,但我需要 div/座位保持静态。我正在寻找任何可以引导我正确方向的想法或示例。

这里有一个非常粗略的想法,关于如何实现它 - http://jsfiddle.net/5c59m5q4/. 不够接近发布为答案,而且我现在没有时间来调整它。 - Harry
那将完美地帮助我开始。当我散步时,我实际上也想到了类似的东西。谢谢你,Harry,如果你想把它写成答案,我很乐意把它作为答案。 - jhorton
请查看此链接(https://dev59.com/K14b5IYBdhLWcg3w9Fur),因为它类似于您要实现的概念。 - jbutler483
1个回答

16

寻找椭圆上的点并进行翻译:

如果您的长方形圆形类似于椭圆,则可以使用数学公式找到椭圆上的点,然后将每个div元素平移到该特定点。

计算椭圆上点(x,y)数学公式(a * cos(t), b * sin(t))。在此公式中,a表示椭圆在x轴上的半径,b表示椭圆在y轴上的半径,t表示弧度角。弧度角=度数角*π/180。

为了利用这种方法,我们需要执行以下操作:

  • div元素绝对置于椭圆的中心点。
  • 计算每个角度对应的(x,y),并使用transform: translateX(...) translateY(...)div平移至其位置。角度步长为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>

这里输入图片描述

注意:坐标是近似值,因此可能不会完全对齐。


使用旋转和缩放变换:(原始想法)

下面的代码片段提供了一个非常粗略的想法,用于将元素沿着圆形定位。它绝不是一个完整的输出,但您可以根据需要进行调整。

组件非常简单:

  • 一个容器元素,它是一个圆圈,并作为参考元素,用于定位座位。
  • 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>

第一种方法是完美且推荐的方法,因为它不会对
元素造成任何扭曲。第二种方法是粗略的想法,避免了复杂的三角计算。

2
哇塞,你在这个问题上真的下了很大功夫!非常感谢你提供如此详细的答案。我一直想知道为什么计算机科学课程中有这么多数学内容,现在我明白了。我会尝试使用第一个答案。再次感谢你的帮助。 - jhorton
实际上,经过进一步的研究,我发现一个问题。我需要网页具有响应式设计。因此,如果我使用该方程式,我需要定义绝对高度和宽度。而在页面调整大小时通过JavaScript设置值将会很昂贵。您知道第一个答案是否可以使用百分比吗? - jhorton
1
@jhorton:第一个答案需要 JS 响应式,因为位置是根据椭圆的 X 和 Y 半径计算的。第二个答案可以在不进行任何额外计算的情况下实现响应式,但正如答案中所指出的那样,它需要一个比例变换来变成椭圆形状,这意味着 div 内部的内容也会被缩放。 - Harry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接